blob: 9c17b97b05442095ecff03ad5e5b605d8daaedc2 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkoe59087d2016-07-04 19:12:19 +03003# ABI Compliance Checker (ABICC) 1.99.22
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 Ponomarenkoe59087d2016-07-04 19:12:19 +030063my $TOOL_VERSION = "1.99.22";
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 Ponomarenkof9f25c92016-07-26 17:20:17 +030014629 if($Type2_Pure{"Name"} eq "void")
14630 { # from something to void*
14631 return 0;
14632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014633 if($Type1_Pure{"Name"}=~/\*/
14634 or $Type2_Pure{"Name"}=~/\*/)
14635 { # compared in detectTypeChange()
14636 return 0;
14637 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014639 my %FloatType = map {$_=>1} (
14640 "float",
14641 "double",
14642 "long double"
14643 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014644
14645 my $T1 = $Type1_Pure{"Type"};
14646 my $T2 = $Type2_Pure{"Type"};
14647
14648 if($T1 eq "Struct"
14649 and $T2 eq "Class")
14650 { # compare as data structures
14651 $T2 = "Struct";
14652 }
14653
14654 if($T1 eq "Class"
14655 and $T2 eq "Struct")
14656 { # compare as data structures
14657 $T1 = "Struct";
14658 }
14659
14660 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014661 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014662 if($T1 eq "Intrinsic"
14663 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014664 { # "int" to "enum"
14665 return 0;
14666 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014667 elsif($T2 eq "Intrinsic"
14668 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014669 { # "enum" to "int"
14670 return 0;
14671 }
14672 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014673 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014674 # ...
14675 return 1;
14676 }
14677 }
14678 else
14679 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014680 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014681 {
14682 if($FloatType{$Type1_Pure{"Name"}}
14683 or $FloatType{$Type2_Pure{"Name"}})
14684 { # "float" to "double"
14685 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014686 if($Level eq "Source")
14687 { # Safe
14688 return 0;
14689 }
14690 else {
14691 return 1;
14692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014693 }
14694 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014695 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014696 {
14697 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14698 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014699 if(not @Membs1
14700 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014701 { # private
14702 return 0;
14703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014704 if($#Membs1!=$#Membs2)
14705 { # different number of elements
14706 return 1;
14707 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014708 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014709 {
14710 foreach my $Pos (@Membs1)
14711 { # compare elements by name and value
14712 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14713 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14714 { # different names
14715 return 1;
14716 }
14717 }
14718 }
14719 else
14720 {
14721 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014722 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014723 if($Level eq "Source")
14724 {
14725 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14726 { # different names
14727 return 1;
14728 }
14729 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014730
14731 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14732 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14733
14734 if($MT1{"Name"} ne $MT2{"Name"}
14735 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14736 {
14737 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14738 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14739
14740 if($PL1 ne $PL2)
14741 { # different pointer level
14742 return 1;
14743 }
14744
14745 # compare base types
14746 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14747 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14748
14749 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14750 { # different types
14751 return 1;
14752 }
14753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014754 }
14755 }
14756 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014757 else
14758 {
14759 # TODO: arrays, etc.
14760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014761 }
14762 return 0;
14763}
14764
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014765sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014766{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014767 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014768 if(not $Type1_Id or not $Type2_Id) {
14769 return ();
14770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014771 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014772 my %Type1 = get_Type($Type1_Id, 1);
14773 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014774 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14775 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014776
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014777 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14778 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 +040014779
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014780 if(defined $UsedDump{1}{"DWARF"})
14781 {
14782 if($Type1_Pure{"Name"} eq "__unknown__"
14783 or $Type2_Pure{"Name"} eq "__unknown__"
14784 or $Type1_Base{"Name"} eq "__unknown__"
14785 or $Type2_Base{"Name"} eq "__unknown__")
14786 { # Error ABI dump
14787 return ();
14788 }
14789 }
14790
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014791 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14792 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014793 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14794 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14795 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14796 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14797 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14798 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14799 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014800 if($Type1{"Name"} eq $Type2{"Name"})
14801 {
14802 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14803 { # will be reported in mergeTypes() as typedef problem
14804 return ();
14805 }
14806 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14807 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14808 if(%Typedef_1 and %Typedef_2)
14809 {
14810 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14811 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14812 { # const Typedef
14813 return ();
14814 }
14815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014816 }
14817 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14818 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014819 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014820 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14821 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822 {
14823 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14824 "Old_Value"=>$Type1_Base{"Name"},
14825 "New_Value"=>$Type2_Base{"Name"},
14826 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014827 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014828 }
14829 else
14830 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014831 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014832 { # format change
14833 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14834 "Old_Value"=>$Type1_Base{"Name"},
14835 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014836 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014837 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014838 }
14839 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14840 {
14841 %{$LocalProblems{$Prefix."_BaseType"}}=(
14842 "Old_Value"=>$Type1_Base{"Name"},
14843 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014844 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014845 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014846 }
14847 }
14848 }
14849 }
14850 elsif($Type1{"Name"} ne $Type2{"Name"})
14851 { # type change
14852 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14853 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014854 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014855 and $Type1_Pure{"Name"} eq "void")
14856 {
14857 %{$LocalProblems{"Return_Type_From_Void"}}=(
14858 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014859 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014861 elsif($Prefix eq "Return"
14862 and $Type2_Pure{"Name"} eq "void")
14863 {
14864 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14865 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014866 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014868 else
14869 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014870 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014871 and $Type1{"Size"} and $Type2{"Size"}
14872 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014873 {
14874 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14875 "Old_Value"=>$Type1{"Name"},
14876 "New_Value"=>$Type2{"Name"},
14877 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014878 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014879 }
14880 else
14881 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014882 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014883 { # format change
14884 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14885 "Old_Value"=>$Type1{"Name"},
14886 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014887 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014888 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889 }
14890 elsif(tNameLock($Type1_Id, $Type2_Id))
14891 { # FIXME: correct this condition
14892 %{$LocalProblems{$Prefix."_Type"}}=(
14893 "Old_Value"=>$Type1{"Name"},
14894 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014895 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014896 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014897 }
14898 }
14899 }
14900 }
14901 }
14902 if($Type1_PLevel!=$Type2_PLevel)
14903 {
14904 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14905 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14906 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014907 if($Level eq "Source")
14908 {
14909 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014910 "Old_Value"=>$Type1_PLevel,
14911 "New_Value"=>$Type2_PLevel);
14912 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014913 else
14914 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014915 if($Type2_PLevel>$Type1_PLevel)
14916 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014917 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14918 "Old_Value"=>$Type1_PLevel,
14919 "New_Value"=>$Type2_PLevel);
14920 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014921 else
14922 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014923 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14924 "Old_Value"=>$Type1_PLevel,
14925 "New_Value"=>$Type2_PLevel);
14926 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014927 }
14928 }
14929 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014930 if($Type1_Pure{"Type"} eq "Array"
14931 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014932 { # base_type[N] -> base_type[N]
14933 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014934 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014935 foreach my $SubProblemType (keys(%SubProblems))
14936 {
14937 $SubProblemType=~s/_Type/_BaseType/g;
14938 next if(defined $LocalProblems{$SubProblemType});
14939 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14940 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14941 }
14942 }
14943 }
14944 return %LocalProblems;
14945}
14946
14947sub tNameLock($$)
14948{
14949 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014950 my $Changed = 0;
14951 if(differentDumps("G"))
14952 { # different GCC versions
14953 $Changed = 1;
14954 }
14955 elsif(differentDumps("V"))
14956 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014957 if(not checkDump(1, "2.20")
14958 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014959 { # latest names update
14960 # 2.6: added restrict qualifier
14961 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014962 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014963 $Changed = 1;
14964 }
14965 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014966
14967 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14968 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14969
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014970 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14971 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14972
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014973 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014974 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014975 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014976 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014977 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014978 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014979 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014980 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014981 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014982 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014983 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14984 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14985 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014986 { # equal base types
14987 return 0;
14988 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014989
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014990 if(not checkDump(1, "2.13")
14991 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014992 { # broken array names in ABI dumps < 2.13
14993 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014994 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014995 return 0;
14996 }
14997 }
14998
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014999 if(not checkDump(1, "2.6")
15000 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015001 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015002 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015003 and $TN2=~/\brestrict\b/) {
15004 return 0;
15005 }
15006 }
15007
15008 if(not checkDump(1, "2.20")
15009 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015010 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015011 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15012 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015013 return 0;
15014 }
15015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015016 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015017 else
15018 {
15019 # typedef struct {...} type_t
15020 # typedef struct type_t {...} type_t
15021 if(index($TN1, " ".$TN2)!=-1)
15022 {
15023 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15024 return 0;
15025 }
15026 }
15027 if(index($TN2, " ".$TN1)!=-1)
15028 {
15029 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15030 return 0;
15031 }
15032 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015033
15034 if($TT1 eq "FuncPtr"
15035 and $TT2 eq "FuncPtr")
15036 {
15037 my $TN1_C = $TN1;
15038 my $TN2_C = $TN2;
15039
15040 $TN1_C=~s/\b(struct|union) //g;
15041 $TN2_C=~s/\b(struct|union) //g;
15042
15043 if($TN1_C eq $TN2_C) {
15044 return 0;
15045 }
15046 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015047 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015048
15049 my ($N1, $N2) = ($TN1, $TN2);
15050 $N1=~s/\b(struct|union) //g;
15051 $N2=~s/\b(struct|union) //g;
15052
15053 if($N1 eq $N2)
15054 { # QList<struct QUrl> and QList<QUrl>
15055 return 0;
15056 }
15057
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015058 return 1;
15059}
15060
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015061sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015062{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015063 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015064 if(defined $Cache{"differentDumps"}{$Check}) {
15065 return $Cache{"differentDumps"}{$Check};
15066 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015067 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015068 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015069 if($Check eq "G")
15070 {
15071 if(getGccVersion(1) ne getGccVersion(2))
15072 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015073 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015075 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015076 if($Check eq "V")
15077 {
15078 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15079 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15080 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015081 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015082 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015084 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015085 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015086}
15087
15088sub formatVersion($$)
15089{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015090 my ($V, $Digits) = @_;
15091 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015092 return join(".", splice(@Elems, 0, $Digits));
15093}
15094
15095sub htmlSpecChars($)
15096{
15097 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015098 if(not $Str) {
15099 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15102 $Str=~s/</&lt;/g;
15103 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15104 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015105 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15106 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015107 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015108 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015109 $Str=~s/\n/<br\/>/g;
15110 $Str=~s/\"/&quot;/g;
15111 $Str=~s/\'/&#39;/g;
15112 return $Str;
15113}
15114
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015115sub xmlSpecChars($)
15116{
15117 my $Str = $_[0];
15118 if(not $Str) {
15119 return $Str;
15120 }
15121
15122 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15123 $Str=~s/</&lt;/g;
15124 $Str=~s/>/&gt;/g;
15125
15126 $Str=~s/\"/&quot;/g;
15127 $Str=~s/\'/&#39;/g;
15128
15129 return $Str;
15130}
15131
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015132sub xmlSpecChars_R($)
15133{
15134 my $Str = $_[0];
15135 if(not $Str) {
15136 return $Str;
15137 }
15138
15139 $Str=~s/&amp;/&/g;
15140 $Str=~s/&lt;/</g;
15141 $Str=~s/&gt;/>/g;
15142
15143 $Str=~s/&quot;/"/g;
15144 $Str=~s/&#39;/'/g;
15145
15146 return $Str;
15147}
15148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015149sub black_name($)
15150{
15151 my $Name = $_[0];
15152 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15153}
15154
15155sub highLight_Signature($)
15156{
15157 my $Signature = $_[0];
15158 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15159}
15160
15161sub highLight_Signature_Italic_Color($)
15162{
15163 my $Signature = $_[0];
15164 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15165}
15166
15167sub separate_symbol($)
15168{
15169 my $Symbol = $_[0];
15170 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15171 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15172 ($Name, $Spec, $Ver) = ($1, $2, $3);
15173 }
15174 return ($Name, $Spec, $Ver);
15175}
15176
15177sub cut_f_attrs($)
15178{
15179 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15180 return $2;
15181 }
15182 return "";
15183}
15184
15185sub highLight_Signature_PPos_Italic($$$$$)
15186{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015187 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15188 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015189 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15190 my $Return = "";
15191 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15192 $Return = $2;
15193 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015194 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015195 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015196 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015198 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015199 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015200 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015201 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202 }
15203 return $Signature;
15204 }
15205 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15206 $Begin.=" " if($Begin!~/ \Z/);
15207 $End = cut_f_attrs($Signature);
15208 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015209 my ($Short, $Params) = split_Signature($Signature);
15210 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015211 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015212 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015213 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015214 $Part=~s/\A\s+|\s+\Z//g;
15215 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15216 if($Part=~/\([\*]+(\w+)\)/i) {
15217 $ParamName = $1;#func-ptr
15218 }
15219 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15220 $ParamName = $1;
15221 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015222 if(not $ParamName)
15223 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224 push(@Parts, $Part_Styled);
15225 next;
15226 }
15227 if($ItalicParams and not $TName_Tid{1}{$Part}
15228 and not $TName_Tid{2}{$Part})
15229 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015230 my $Style = "<i>$ParamName</i>";
15231
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015232 if($Param_Pos ne ""
15233 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015234 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015235 }
15236 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015237 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015238 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015239
15240 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015241 }
15242 $Part_Styled=~s/,(\w)/, $1/g;
15243 push(@Parts, $Part_Styled);
15244 }
15245 if(@Parts)
15246 {
15247 foreach my $Num (0 .. $#Parts)
15248 {
15249 if($Num==$#Parts)
15250 { # add ")" to the last parameter
15251 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15252 }
15253 elsif(length($Parts[$Num])<=45) {
15254 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15255 }
15256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015257 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015258 }
15259 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015260 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015261 }
15262 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015263 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015265 $Signature=~s!\[\]![&#160;]!g;
15266 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015267 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15268 if($SymbolVersion) {
15269 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15270 }
15271 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015272}
15273
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015274sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015275{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015276 my $Signature = $_[0];
15277 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15278 {
15279 $Signature=~s/\A\Q$ShortName\E\(//g;
15280 cut_f_attrs($Signature);
15281 $Signature=~s/\)\Z//;
15282 return ($ShortName, $Signature);
15283 }
15284
15285 # error
15286 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015287}
15288
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015289sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015290{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015291 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015292 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015293 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15294 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015295 foreach my $Pos (0 .. length($Params) - 1)
15296 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015297 my $S = substr($Params, $Pos, 1);
15298 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015299 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015300 }
15301 if($S eq "," and
15302 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015303 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015304 if($Comma)
15305 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015306 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015307 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015308 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015309 }
15310 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015311 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015312 }
15313 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015314 if(not $Sp)
15315 { # remove spaces
15316 foreach (@Parts)
15317 {
15318 s/\A //g;
15319 s/ \Z//g;
15320 }
15321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322 return @Parts;
15323}
15324
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015325sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015326{
15327 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015328 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015329 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015330 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15331 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015332 $Center+=length($1);
15333 }
15334 foreach my $Pos (0 .. length($Sign)-1)
15335 {
15336 my $S = substr($Sign, $Pos, 1);
15337 if($S eq $Target)
15338 {
15339 if($B{"("}==$B{")"}
15340 and $B{"<"}==$B{">"}) {
15341 return $Center;
15342 }
15343 }
15344 if(defined $B{$S}) {
15345 $B{$S}+=1;
15346 }
15347 $Center+=1;
15348 }
15349 return 0;
15350}
15351
15352sub appendFile($$)
15353{
15354 my ($Path, $Content) = @_;
15355 return if(not $Path);
15356 if(my $Dir = get_dirname($Path)) {
15357 mkpath($Dir);
15358 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015359 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015360 print FILE $Content;
15361 close(FILE);
15362}
15363
15364sub writeFile($$)
15365{
15366 my ($Path, $Content) = @_;
15367 return if(not $Path);
15368 if(my $Dir = get_dirname($Path)) {
15369 mkpath($Dir);
15370 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015371 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015372 print FILE $Content;
15373 close(FILE);
15374}
15375
15376sub readFile($)
15377{
15378 my $Path = $_[0];
15379 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015380 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015381 local $/ = undef;
15382 my $Content = <FILE>;
15383 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015384 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015385 $Content=~s/\r/\n/g;
15386 }
15387 return $Content;
15388}
15389
15390sub get_filename($)
15391{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015392 if(defined $Cache{"get_filename"}{$_[0]}) {
15393 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015394 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015395 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15396 return ($Cache{"get_filename"}{$_[0]}=$1);
15397 }
15398 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015399}
15400
15401sub get_dirname($)
15402{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015403 if(defined $Cache{"get_dirname"}{$_[0]}) {
15404 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015405 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015406 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15407 return ($Cache{"get_dirname"}{$_[0]}=$1);
15408 }
15409 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015410}
15411
15412sub separate_path($) {
15413 return (get_dirname($_[0]), get_filename($_[0]));
15414}
15415
15416sub esc($)
15417{
15418 my $Str = $_[0];
15419 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15420 return $Str;
15421}
15422
15423sub readLineNum($$)
15424{
15425 my ($Path, $Num) = @_;
15426 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015427 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015428 foreach (1 ... $Num) {
15429 <FILE>;
15430 }
15431 my $Line = <FILE>;
15432 close(FILE);
15433 return $Line;
15434}
15435
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015436sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015438 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015439 return () if(not $Path or not -f $Path);
15440 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015441 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15442 {
15443 foreach my $AttrVal (split(/;/, $1))
15444 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015445 if($AttrVal=~/(.+):(.+)/)
15446 {
15447 my ($Name, $Value) = ($1, $2);
15448 $Attributes{$Name} = $Value;
15449 }
15450 }
15451 }
15452 return \%Attributes;
15453}
15454
15455sub is_abs($) {
15456 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15457}
15458
15459sub get_abs_path($)
15460{ # abs_path() should NOT be called for absolute inputs
15461 # because it can change them
15462 my $Path = $_[0];
15463 if(not is_abs($Path)) {
15464 $Path = abs_path($Path);
15465 }
15466 return $Path;
15467}
15468
15469sub get_OSgroup()
15470{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015471 my $N = $Config{"osname"};
15472 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015473 return "macos";
15474 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015475 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015476 return "bsd";
15477 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015478 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015479 return "beos";
15480 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015481 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015482 return "symbian";
15483 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015484 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015485 return "windows";
15486 }
15487 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015488 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015489 }
15490}
15491
15492sub getGccVersion($)
15493{
15494 my $LibVersion = $_[0];
15495 if($GCC_VERSION{$LibVersion})
15496 { # dump version
15497 return $GCC_VERSION{$LibVersion};
15498 }
15499 elsif($UsedDump{$LibVersion}{"V"})
15500 { # old-version dumps
15501 return "unknown";
15502 }
15503 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15504 if(not $GccVersion) {
15505 return "unknown";
15506 }
15507 return $GccVersion;
15508}
15509
15510sub showArch($)
15511{
15512 my $Arch = $_[0];
15513 if($Arch eq "arm"
15514 or $Arch eq "mips") {
15515 return uc($Arch);
15516 }
15517 return $Arch;
15518}
15519
15520sub getArch($)
15521{
15522 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015523
15524 if($TargetArch) {
15525 return $TargetArch;
15526 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015527 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015528 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 return $CPU_ARCH{$LibVersion};
15530 }
15531 elsif($UsedDump{$LibVersion}{"V"})
15532 { # old-version dumps
15533 return "unknown";
15534 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015535
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015536 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015537}
15538
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015539sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015540{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015541 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015542
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015543 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015544 if(getArch(1) ne getArch(2)
15545 or getArch(1) eq "unknown"
15546 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015547 { # don't show architecture in the header
15548 $ArchInfo="";
15549 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015550 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015551 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015552 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015553 }
15554 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015555 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015556 }
15557 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015558 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015559 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015560
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015561 my $V1 = $Descriptor{1}{"Version"};
15562 my $V2 = $Descriptor{2}{"Version"};
15563
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015564 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15565 {
15566 my $M1 = $UsedDump{1}{"M"};
15567 my $M2 = $UsedDump{2}{"M"};
15568
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015569 my $M1S = $M1;
15570 my $M2S = $M2;
15571
15572 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15573 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15574
15575 if($M1S eq $M2S
15576 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015577 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015578 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15579 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015580 }
15581 else
15582 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015583 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15584 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015585 }
15586 }
15587 else
15588 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015589 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015590 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015591 }
15592
15593 $Title .= $ArchInfo;
15594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015596 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015597 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015598 $Title = "<h1>".$Title."</h1>\n";
15599 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015600}
15601
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015602sub get_CheckedHeaders($)
15603{
15604 my $LibVersion = $_[0];
15605
15606 my @Headers = ();
15607
15608 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15609 {
15610 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015611
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015612 if(not is_target_header($File, $LibVersion)) {
15613 next;
15614 }
15615
15616 if(skipHeader($File, $LibVersion)) {
15617 next;
15618 }
15619
15620 push(@Headers, $Path);
15621 }
15622
15623 return @Headers;
15624}
15625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015626sub get_SourceInfo()
15627{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015628 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015629
15630 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015631 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015632 $CheckedHeaders = "<a name='Headers'></a>";
15633 if($OldStyle) {
15634 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15635 }
15636 else {
15637 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15638 }
15639 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015640 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 +040015641 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015642 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15643 my $Name = get_filename($Identity);
15644 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15645 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015646 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015647 $CheckedHeaders .= "</div>\n";
15648 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015649 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015650
15651 if(my @Sources = keys(%{$Registered_Sources{1}}))
15652 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015653 $CheckedSources = "<a name='Sources'></a>";
15654 if($OldStyle) {
15655 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15656 }
15657 else {
15658 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15659 }
15660 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015661 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15662 {
15663 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15664 my $Name = get_filename($Identity);
15665 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15666 $CheckedSources .= $Name.$Comment."<br/>\n";
15667 }
15668 $CheckedSources .= "</div>\n";
15669 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15670 }
15671
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015672 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015674 $CheckedLibs = "<a name='Libs'></a>";
15675 if($OldStyle) {
15676 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15677 }
15678 else {
15679 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15680 }
15681 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15682 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015683 $CheckedLibs .= $Library."<br/>\n";
15684 }
15685 $CheckedLibs .= "</div>\n";
15686 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015687 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015688
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015689 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15690}
15691
15692sub get_ObjTitle()
15693{
15694 if(defined $UsedDump{1}{"DWARF"}) {
15695 return "Objects";
15696 }
15697 else {
15698 return ucfirst($SLIB_TYPE)." Libraries";
15699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015700}
15701
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015702sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015703{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015704 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015705 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015706
15707 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015708 {
15709 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015710 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015711 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015712 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015713 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015714 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015715 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015716
15717 if($Severity ne $TargetSeverity) {
15718 next;
15719 }
15720
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015721 if($Kinds_Target{$Kind}{$Target}) {
15722 next;
15723 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015724
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015725 $Kinds_Target{$Kind}{$Target} = 1;
15726 $Type_Problems_Count += 1;
15727 }
15728 }
15729 }
15730 return $Type_Problems_Count;
15731}
15732
15733sub get_Summary($)
15734{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015735 my $Level = $_[0];
15736 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015737 $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 +040015738 %{$RESULT{$Level}} = (
15739 "Problems"=>0,
15740 "Warnings"=>0,
15741 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015742 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015743 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015745 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015746 {
15747 if(not defined $CompatRules{$Level}{$Kind})
15748 { # unknown rule
15749 if(not $UnknownRules{$Level}{$Kind})
15750 { # only one warning
15751 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15752 $UnknownRules{$Level}{$Kind}=1;
15753 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015754 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015755 }
15756 }
15757 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015758 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15759 {
15760 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15761 {
15762 if(not defined $CompatRules{$Level}{$Kind})
15763 { # unknown rule
15764 if(not $UnknownRules{$Level}{$Kind})
15765 { # only one warning
15766 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15767 $UnknownRules{$Level}{$Kind}=1;
15768 }
15769 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15770 }
15771 }
15772 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015773 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015775 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015776 {
15777 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15778 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015779 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015781 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015782 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015783 $Added += 1;
15784 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015785 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015786 {
15787 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015788 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015789 }
15790 else
15791 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015792 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015793 $I_Other += 1;
15794 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015795 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015796 $I_Problems_High += 1;
15797 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015798 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799 $I_Problems_Medium += 1;
15800 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015801 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015802 $I_Problems_Low += 1;
15803 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015804 if(($Severity ne "Low" or $StrictCompat)
15805 and $Severity ne "Safe") {
15806 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015807 }
15808 }
15809 }
15810 }
15811 }
15812 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015813
15814 my %MethodTypeIndex = ();
15815
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015816 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015817 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015818 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15819 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 {
15821 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15822 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015823 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15824 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015825 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015826 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15827 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015828
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015829 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15830 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015831 next;
15832 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015833 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15834 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15835
15836 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015837
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015838 if(($Severity ne "Low" or $StrictCompat)
15839 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015840 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015841 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015842 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015843 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015844 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015845 }
15846 }
15847 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015848 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015850 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015851 }
15852 }
15853 }
15854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015855
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015856 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15857 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15858 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15859 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015860
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015861 # changed and removed public symbols
15862 my $SCount = keys(%{$CheckedSymbols{$Level}});
15863 if($ExtendedCheck)
15864 { # don't count external_func_0 for constants
15865 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015866 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015867 if($SCount)
15868 {
15869 my %Weight = (
15870 "High" => 100,
15871 "Medium" => 50,
15872 "Low" => 25
15873 );
15874 foreach (keys(%{$TotalAffected{$Level}})) {
15875 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015876 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015877 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015878 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015879 else {
15880 $RESULT{$Level}{"Affected"} = 0;
15881 }
15882
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015883 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15884 if($RESULT{$Level}{"Affected"}>=100) {
15885 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015886 }
15887
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015888 $RESULT{$Level}{"Problems"} += $Removed;
15889 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015890 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015891 if($StrictCompat) {
15892 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15893 }
15894 else {
15895 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015897
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015898 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015899 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015900 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015901 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015902 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015903 if($Severity eq "Safe")
15904 {
15905 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015906 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015907 elsif($Severity eq "Low")
15908 {
15909 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015910 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015911 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015912 }
15913
15914 if($C_Problems_Low)
15915 {
15916 if($StrictCompat) {
15917 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15918 }
15919 else {
15920 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015921 }
15922 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015923 if($RESULT{$Level}{"Problems"}
15924 and $RESULT{$Level}{"Affected"}) {
15925 $RESULT{$Level}{"Verdict"} = "incompatible";
15926 }
15927 else {
15928 $RESULT{$Level}{"Verdict"} = "compatible";
15929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015930
15931 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15932 if(not $TotalTypes)
15933 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015934 $TotalTypes = keys(%{$TName_Tid{1}});
15935 }
15936
15937 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15938 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15939
15940 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15941
15942 if($ReportFormat eq "xml")
15943 { # XML
15944 # test info
15945 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15946 $TestInfo .= " <version1>\n";
15947 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015948 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015949 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15950 $TestInfo .= " </version1>\n";
15951
15952 $TestInfo .= " <version2>\n";
15953 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015954 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15956 $TestInfo .= " </version2>\n";
15957 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15958
15959 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015960 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015962 $TestResults .= " <headers>\n";
15963 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15964 {
15965 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15966 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15967 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15968 }
15969 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015970 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015971
15972 if(my @Sources = keys(%{$Registered_Sources{1}}))
15973 {
15974 $TestResults .= " <sources>\n";
15975 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15976 {
15977 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15978 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15979 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15980 }
15981 $TestResults .= " </sources>\n";
15982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015983
15984 $TestResults .= " <libs>\n";
15985 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15986 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015987 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015988 $TestResults .= " <name>$Library</name>\n";
15989 }
15990 $TestResults .= " </libs>\n";
15991
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015992 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993 $TestResults .= " <types>".$TotalTypes."</types>\n";
15994
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15996 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015997 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15998
15999 # problem summary
16000 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16001 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16002
16003 $Problem_Summary .= " <problems_with_types>\n";
16004 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16005 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16006 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16007 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16008 $Problem_Summary .= " </problems_with_types>\n";
16009
16010 $Problem_Summary .= " <problems_with_symbols>\n";
16011 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16012 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16013 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 $Problem_Summary .= " </problems_with_symbols>\n";
16016
16017 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016018 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016019 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016020
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016021 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16022
16023 return ($TestInfo.$TestResults.$Problem_Summary, "");
16024 }
16025 else
16026 { # HTML
16027 # test info
16028 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016029 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016030
16031 if($TargetComponent eq "library") {
16032 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16033 }
16034 else {
16035 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16036 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016037
16038 my (@VInf1, @VInf2, $AddTestInfo) = ();
16039 if($Arch1 ne "unknown"
16040 and $Arch2 ne "unknown")
16041 { # CPU arch
16042 if($Arch1 eq $Arch2)
16043 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016044 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016045 }
16046 else
16047 { # go to the version number
16048 push(@VInf1, showArch($Arch1));
16049 push(@VInf2, showArch($Arch2));
16050 }
16051 }
16052 if($GccV1 ne "unknown"
16053 and $GccV2 ne "unknown"
16054 and $OStarget ne "windows")
16055 { # GCC version
16056 if($GccV1 eq $GccV2)
16057 { # go to the separate section
16058 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16059 }
16060 else
16061 { # go to the version number
16062 push(@VInf1, "gcc ".$GccV1);
16063 push(@VInf2, "gcc ".$GccV2);
16064 }
16065 }
16066 # show long version names with GCC version and CPU architecture name (if different)
16067 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16068 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16069 $TestInfo .= $AddTestInfo;
16070 #if($COMMON_LANGUAGE{1}) {
16071 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16072 #}
16073 if($ExtendedCheck) {
16074 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016076 if($JoinReport)
16077 {
16078 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016079 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016080 }
16081 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016082 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016083 }
16084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016085 $TestInfo .= "</table>\n";
16086
16087 # test results
16088 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016089 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016090
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016091 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016092 {
16093 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16094 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16095 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016096
16097 if(my @Sources = keys(%{$Registered_Sources{1}}))
16098 {
16099 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16100 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016102
16103 if(not $ExtendedCheck)
16104 {
16105 my $Libs_Link = "0";
16106 $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 +040016107 $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 +040016108 }
16109
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016110 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016111
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016112 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016113 if($JoinReport) {
16114 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16115 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016116
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016117 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016118
16119 $TestResults .= "<tr><th>Compatibility</th>\n";
16120 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16121 {
16122 my $Cl = "incompatible";
16123 if($BC_Rate>=90) {
16124 $Cl = "warning";
16125 }
16126 elsif($BC_Rate>=80) {
16127 $Cl = "almost_compatible";
16128 }
16129
16130 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016131 }
16132 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016133 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016134 }
16135 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016136 $TestResults .= "</table>\n";
16137
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016138 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016139 # problem summary
16140 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016141 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016142 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16143
16144 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016145 if($Added>0)
16146 {
16147 if($JoinReport) {
16148 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16149 }
16150 else {
16151 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16152 }
16153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016154 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016155 $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 +040016156
16157 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016158 if($Removed>0)
16159 {
16160 if($JoinReport) {
16161 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16162 }
16163 else {
16164 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16165 }
16166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016167 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016168 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016169 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170
16171 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172 $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 +040016173 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016174 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016175 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016176
16177 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016178 $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 +040016179 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016180 $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 +040016181
16182 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016183 $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 +040016184 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016185 $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 +040016186
16187 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 $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 +040016189 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016190 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016191 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016192
16193 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194 $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 +040016195 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016196 $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 +040016197
16198 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016199 $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 +040016200 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016201 $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 +040016202
16203 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016204 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16205 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016206 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016207 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016208 $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 +040016209
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016210 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016211 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016212 {
16213 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016214 $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 +030016215 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016217
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016218 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016219 {
16220 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016221 $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 +030016222 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016225 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016226 {
16227 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016228 $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 +030016229 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016230 }
16231
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016232 $META_DATA .= "tool_version:$TOOL_VERSION";
16233 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016235 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16236 }
16237}
16238
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016239sub getStyle($$$)
16240{
16241 my ($Subj, $Act, $Num) = @_;
16242 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016243 "Added"=>"new",
16244 "Removed"=>"failed",
16245 "Safe"=>"passed",
16246 "Low"=>"warning",
16247 "Medium"=>"failed",
16248 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016249 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016250
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016251 if($Num>0) {
16252 return " class='".$Style{$Act}."'";
16253 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016254
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016255 return "";
16256}
16257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258sub show_number($)
16259{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016260 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016261 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016262 my $Num = cut_off_number($_[0], 2, 0);
16263 if($Num eq "0")
16264 {
16265 foreach my $P (3 .. 7)
16266 {
16267 $Num = cut_off_number($_[0], $P, 1);
16268 if($Num ne "0") {
16269 last;
16270 }
16271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272 }
16273 if($Num eq "0") {
16274 $Num = $_[0];
16275 }
16276 return $Num;
16277 }
16278 return $_[0];
16279}
16280
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016281sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016282{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016283 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 if($num!~/\./)
16285 {
16286 $num .= ".";
16287 foreach (1 .. $digs_to_cut-1) {
16288 $num .= "0";
16289 }
16290 }
16291 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16292 {
16293 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16294 $num .= "0";
16295 }
16296 }
16297 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16298 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16299 }
16300 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016301 if($z) {
16302 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016304 return $num;
16305}
16306
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016307sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016309 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016310 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016311
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016312 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016313 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16314 {
16315 my $Header = $Constants{1}{$Constant}{"Header"};
16316 if(not $Header)
16317 { # added
16318 $Header = $Constants{2}{$Constant}{"Header"}
16319 }
16320
16321 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16322 {
16323 if(not defined $CompatRules{$Level}{$Kind}) {
16324 next;
16325 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016326 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016327 next;
16328 }
16329 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016331 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016333 if($ReportFormat eq "xml")
16334 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016335 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016336 {
16337 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016338 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016339 {
16340 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016341 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16342 {
16343 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16344 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16345 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016346
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016347 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16348 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16349 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016350 if($Overcome) {
16351 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16352 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016353 $CHANGED_CONSTANTS .= " </problem>\n";
16354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016355 $CHANGED_CONSTANTS .= " </constant>\n";
16356 }
16357 $CHANGED_CONSTANTS .= " </header>\n";
16358 }
16359 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16360 }
16361 else
16362 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016363 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016364 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016365 {
16366 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016367 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016369 my $Report = "";
16370
16371 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16372 {
16373 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16374 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016375 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016376 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016377 }
16378 if($Report)
16379 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016380 $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 +030016381 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016382 $Report = insertIDs($Report);
16383 }
16384 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016385 }
16386 $CHANGED_CONSTANTS .= "<br/>\n";
16387 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016388 if($CHANGED_CONSTANTS)
16389 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016390 my $Title = "Problems with Constants, $TargetSeverity Severity";
16391 if($TargetSeverity eq "Safe")
16392 { # Safe Changes
16393 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016394 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016395 if($OldStyle) {
16396 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16397 }
16398 else {
16399 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16400 }
16401 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016402 }
16403 }
16404 return $CHANGED_CONSTANTS;
16405}
16406
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016407sub getTitle($$$)
16408{
16409 my ($Header, $Library, $NameSpace) = @_;
16410 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016411
16412 # if($Library and $Library!~/\.\w+\Z/) {
16413 # $Library .= " (.$LIB_EXT)";
16414 # }
16415
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016416 if($Header and $Library)
16417 {
16418 $Title .= "<span class='h_name'>$Header</span>";
16419 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16420 }
16421 elsif($Library) {
16422 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16423 }
16424 elsif($Header) {
16425 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16426 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016427
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016428 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016429 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016430 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016431
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016432 return $Title;
16433}
16434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435sub get_Report_Added($)
16436{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016437 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016438 my $ADDED_INTERFACES = "";
16439 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016442 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016443 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016444 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016445 {
16446 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16447 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016448 if($Level eq "Source" and $ReportFormat eq "html")
16449 { # do not show library name in HTML report
16450 $DyLib = "";
16451 }
16452 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 }
16454 }
16455 }
16456 if($ReportFormat eq "xml")
16457 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016458 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016459 {
16460 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016461 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016462 {
16463 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016464 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16466 }
16467 $ADDED_INTERFACES .= " </library>\n";
16468 }
16469 $ADDED_INTERFACES .= " </header>\n";
16470 }
16471 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16472 }
16473 else
16474 { # HTML
16475 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016476 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016477 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016478 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016479 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 my %NameSpaceSymbols = ();
16481 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016482 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016484 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016486 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16487 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016488 foreach my $Interface (@SortedInterfaces)
16489 {
16490 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016491 my $Signature = get_Signature($Interface, 2);
16492 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016493 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016495 if($Interface=~/\A(_Z|\?)/)
16496 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016497 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016498 $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 +040016499 }
16500 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016501 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016502 }
16503 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016504 else
16505 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016508 }
16509 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016510 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 }
16512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016514 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016516 }
16517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016518 if($ADDED_INTERFACES)
16519 {
16520 my $Anchor = "<a name='Added'></a>";
16521 if($JoinReport) {
16522 $Anchor = "<a name='".$Level."_Added'></a>";
16523 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016524 if($OldStyle) {
16525 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16526 }
16527 else {
16528 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16529 }
16530 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016531 }
16532 }
16533 return $ADDED_INTERFACES;
16534}
16535
16536sub get_Report_Removed($)
16537{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016538 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016539 my $REMOVED_INTERFACES = "";
16540 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016541 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016543 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016546 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016547 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16548 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016549 if($Level eq "Source" and $ReportFormat eq "html")
16550 { # do not show library name in HTML report
16551 $DyLib = "";
16552 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016553 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 }
16555 }
16556 }
16557 if($ReportFormat eq "xml")
16558 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 {
16561 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016562 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 {
16564 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016565 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16566 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016567 }
16568 $REMOVED_INTERFACES .= " </library>\n";
16569 }
16570 $REMOVED_INTERFACES .= " </header>\n";
16571 }
16572 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16573 }
16574 else
16575 { # HTML
16576 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016579 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016580 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016581 my %NameSpaceSymbols = ();
16582 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016583 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016587 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16588 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016589 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 {
16591 $Removed_Number += 1;
16592 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016593 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016594 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016595 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016597 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016598 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016599 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016600 $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 +040016601 }
16602 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016603 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 }
16605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016606 else
16607 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016608 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016609 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 }
16611 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016612 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016613 }
16614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016615 }
16616 }
16617 $REMOVED_INTERFACES .= "<br/>\n";
16618 }
16619 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016620 if($REMOVED_INTERFACES)
16621 {
16622 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16623 if($JoinReport) {
16624 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16625 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016626 if($OldStyle) {
16627 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16628 }
16629 else {
16630 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16631 }
16632
16633 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 }
16635 }
16636 return $REMOVED_INTERFACES;
16637}
16638
16639sub getXmlParams($$)
16640{
16641 my ($Content, $Problem) = @_;
16642 return "" if(not $Content or not $Problem);
16643 my %XMLparams = ();
16644 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16645 {
16646 my $Macro = "\@".lc($Attr);
16647 if($Content=~/\Q$Macro\E/) {
16648 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16649 }
16650 }
16651 my @PString = ();
16652 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016653 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 }
16655 if(@PString) {
16656 return " ".join(" ", @PString);
16657 }
16658 else {
16659 return "";
16660 }
16661}
16662
16663sub addMarkup($)
16664{
16665 my $Content = $_[0];
16666 # auto-markup
16667 $Content=~s/\n[ ]*//; # spaces
16668 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16669 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016670 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016671 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16672 if($Content=~/\ANOTE:/)
16673 { # notes
16674 $Content=~s!(NOTE):!<b>$1</b>:!g;
16675 }
16676 else {
16677 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16678 }
16679 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16680 my @Keywords = (
16681 "void",
16682 "const",
16683 "static",
16684 "restrict",
16685 "volatile",
16686 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016687 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016688 );
16689 my $MKeys = join("|", @Keywords);
16690 foreach (@Keywords) {
16691 $MKeys .= "|non-".$_;
16692 }
16693 $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 +040016694
16695 # Markdown
16696 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16697 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 return $Content;
16699}
16700
16701sub applyMacroses($$$$)
16702{
16703 my ($Level, $Kind, $Content, $Problem) = @_;
16704 return "" if(not $Content or not $Problem);
16705 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16706 $Content = addMarkup($Content);
16707 # macros
16708 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16709 {
16710 my $Macro = "\@".lc($Attr);
16711 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016712 if(not defined $Value
16713 or $Value eq "") {
16714 next;
16715 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016716
16717 if(index($Content, $Macro)==-1) {
16718 next;
16719 }
16720
16721 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16722 and $Kind!~/_Type_/
16723 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016725 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016726 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016727 $Value = black_name($Value);
16728 }
16729 elsif($Value=~/\s/) {
16730 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16731 }
16732 elsif($Value=~/\A\d+\Z/
16733 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16734 { # bits to bytes
16735 if($Value % $BYTE_SIZE)
16736 { # bits
16737 if($Value==1) {
16738 $Value = "<b>".$Value."</b> bit";
16739 }
16740 else {
16741 $Value = "<b>".$Value."</b> bits";
16742 }
16743 }
16744 else
16745 { # bytes
16746 $Value /= $BYTE_SIZE;
16747 if($Value==1) {
16748 $Value = "<b>".$Value."</b> byte";
16749 }
16750 else {
16751 $Value = "<b>".$Value."</b> bytes";
16752 }
16753 }
16754 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016755 else
16756 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016757 $Value = "<b>".htmlSpecChars($Value)."</b>";
16758 }
16759 $Content=~s/\Q$Macro\E/$Value/g;
16760 }
16761
16762 if($Content=~/(\A|[^\@\w])\@\w/)
16763 {
16764 if(not $IncompleteRules{$Level}{$Kind})
16765 { # only one warning
16766 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16767 $IncompleteRules{$Level}{$Kind} = 1;
16768 }
16769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016770 return $Content;
16771}
16772
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016773sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016774{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016775 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016776 my $INTERFACE_PROBLEMS = "";
16777 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016778
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016779 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016780 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016781 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16782 if($SV and defined $CompatProblems{$Level}{$SN}) {
16783 next;
16784 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016785 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16786 my $DyLib = $Symbol_Library{1}{$Symbol};
16787 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16788 { # Symbol with Version
16789 $DyLib = $Symbol_Library{1}{$VSym};
16790 }
16791 if(not $DyLib)
16792 { # const global data
16793 $DyLib = "";
16794 }
16795 if($Level eq "Source" and $ReportFormat eq "html")
16796 { # do not show library name in HTML report
16797 $DyLib = "";
16798 }
16799
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016800 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016801 {
16802 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016803 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016804 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016805 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16806 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016808 if($Severity eq $TargetSeverity)
16809 {
16810 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16811 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016812 }
16813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 }
16815 }
16816 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016817
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016818 if($ReportFormat eq "xml")
16819 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016820 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 {
16822 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016823 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 {
16825 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016826 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16827 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 {
16829 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016830 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016831 {
16832 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16833 {
16834 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016835 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016836
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016837 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16838 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16839 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16840 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16841 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016842 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16843 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016845 $INTERFACE_PROBLEMS .= " </problem>\n";
16846 }
16847 }
16848 $INTERFACE_PROBLEMS .= " </symbol>\n";
16849 }
16850 $INTERFACE_PROBLEMS .= " </library>\n";
16851 }
16852 $INTERFACE_PROBLEMS .= " </header>\n";
16853 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016854 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016855 }
16856 else
16857 { # HTML
16858 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016859 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016860 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016861 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016863 my (%NameSpaceSymbols, %NewSignature) = ();
16864 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016865 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016866 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016867 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016870 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 +040016871 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 my $Signature = get_Signature($Symbol, 1);
16874 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016876 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016877 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016878 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016879 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016880 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016881 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016883 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 }
16885 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16886 {
16887 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016888 $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 +040016889 $ProblemNum += 1;
16890 $ProblemsNum += 1;
16891 }
16892 }
16893 }
16894 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016895 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016897 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016898 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016899 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016901
16902 if($NameSpace)
16903 {
16904 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16905 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016906 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016907
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016908 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
16909 if($OldStyle) {
16910 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
16911 }
16912 else {
16913 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
16914 }
16915 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016916 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016917
16918 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016919 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016920 if($NameSpace) {
16921 $NSign = cut_Namespace($NSign, $NameSpace);
16922 }
16923 $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 +040016924 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016925
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016926 if($Symbol=~/\A(_Z|\?)/) {
16927 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16928 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016929
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016930 $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 +040016931 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 }
16933 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016934 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 }
16936 }
16937 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016938
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016939 if($INTERFACE_PROBLEMS)
16940 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016941 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16942 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16943 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 { # Safe Changes
16945 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016947 if($OldStyle) {
16948 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
16949 }
16950 else {
16951 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
16952 }
16953 $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 +040016954 }
16955 }
16956 return $INTERFACE_PROBLEMS;
16957}
16958
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016959sub cut_Namespace($$)
16960{
16961 my ($N, $Ns) = @_;
16962 $N=~s/\b\Q$Ns\E:://g;
16963 return $N;
16964}
16965
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016966sub get_Report_TypeProblems($$)
16967{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016968 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016969 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016970
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016971 my %ReportMap = ();
16972 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016973
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016974 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016976 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
16977
16978 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016979 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016980 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016982 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016983 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016984
16985 if($Severity eq $TargetSeverity)
16986 {
16987 $ReportMap{$HeaderName}{$TypeName} = 1;
16988 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016990 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016992 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016993
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994 if($ReportFormat eq "xml")
16995 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016996 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016997 {
16998 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016999 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017001 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017002 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017003 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017005 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017006 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017007 $Kinds_Locations{$Kind}{$Location} = 1;
17008
17009 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17010 if($Kinds_Target{$Kind}{$Target}) {
17011 next;
17012 }
17013 $Kinds_Target{$Kind}{$Target} = 1;
17014
17015 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017016 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17017 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17018 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17019 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17020 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017021 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17022 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017024 $TYPE_PROBLEMS .= " </problem>\n";
17025 }
17026 }
Andrey Ponomarenkof9f25c92016-07-26 17:20:17 +030017027 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
17028 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017029 $TYPE_PROBLEMS .= showVTables($TypeName);
17030 }
17031 $TYPE_PROBLEMS .= " </type>\n";
17032 }
17033 $TYPE_PROBLEMS .= " </header>\n";
17034 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017035 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017036 }
17037 else
17038 { # HTML
17039 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017040 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017041 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017042 my (%NameSpace_Type) = ();
17043 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017044 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 }
17046 foreach my $NameSpace (sort keys(%NameSpace_Type))
17047 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017048 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017049 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 +040017050 foreach my $TypeName (@SortedTypes)
17051 {
17052 my $ProblemNum = 1;
17053 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017054 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017055
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017056 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017057 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017058 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017059 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017060 $Kinds_Locations{$Kind}{$Location} = 1;
17061
17062 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17063 if($Kinds_Target{$Kind}{$Target}) {
17064 next;
17065 }
17066 $Kinds_Target{$Kind}{$Target} = 1;
17067
17068 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017069 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17070 {
17071 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017072 $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 +040017073 $ProblemNum += 1;
17074 $ProblemsNum += 1;
17075 }
17076 }
17077 }
17078 $ProblemNum -= 1;
17079 if($TYPE_REPORT)
17080 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017081 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017082 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017083 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017084 $ShowVTables = showVTables($TypeName);
17085 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017086
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017087 my $ShowType = show_Type($TypeName, 1, 1);
17088
17089 if($NameSpace)
17090 {
17091 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17092 $ShowType = cut_Namespace($ShowType, $NameSpace);
17093 $Affected = cut_Namespace($Affected, $NameSpace);
17094 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17095 }
17096
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017097 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17098 if($OldStyle) {
17099 $TYPE_PROBLEMS .= " ($ProblemNum)";
17100 }
17101 else {
17102 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17103 }
17104 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017105 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17106 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17107 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17108 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017109 }
17110 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017111 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017112 }
17113 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017114
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017115 if($TYPE_PROBLEMS)
17116 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017117 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17118 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017119 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017120 { # Safe Changes
17121 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017123 if($OldStyle) {
17124 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17125 }
17126 else {
17127 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17128 }
17129 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017130 }
17131 }
17132 return $TYPE_PROBLEMS;
17133}
17134
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017135sub show_Type($$$)
17136{
17137 my ($Name, $Html, $LibVersion) = @_;
17138 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17139 $TType = lc($TType);
17140 if($TType=~/struct|union|enum/) {
17141 $Name=~s/\A\Q$TType\E //g;
17142 }
17143 if($Html) {
17144 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17145 }
17146 else {
17147 $Name = $TType." ".$Name;
17148 }
17149 return $Name;
17150}
17151
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017152sub get_Anchor($$$)
17153{
17154 my ($Kind, $Level, $Severity) = @_;
17155 if($JoinReport)
17156 {
17157 if($Severity eq "Safe") {
17158 return "Other_".$Level."_Changes_In_".$Kind."s";
17159 }
17160 else {
17161 return $Kind."_".$Level."_Problems_".$Severity;
17162 }
17163 }
17164 else
17165 {
17166 if($Severity eq "Safe") {
17167 return "Other_Changes_In_".$Kind."s";
17168 }
17169 else {
17170 return $Kind."_Problems_".$Severity;
17171 }
17172 }
17173}
17174
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017175sub showVTables($)
17176{
17177 my $TypeName = $_[0];
17178 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017179 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017180 if(defined $Type1{"VTable"}
17181 and keys(%{$Type1{"VTable"}}))
17182 {
17183 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017184 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017185 if(defined $Type2{"VTable"}
17186 and keys(%{$Type2{"VTable"}}))
17187 {
17188 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17189 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017190 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017191 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017192 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17193 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017194 }
17195 my $VTABLES = "";
17196 if($ReportFormat eq "xml")
17197 { # XML
17198 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017199 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017200 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017201 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017202 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17203 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204 $VTABLES .= " </entry>\n";
17205 }
17206 $VTABLES .= " </vtable>\n\n";
17207 }
17208 else
17209 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017210 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017211 $VTABLES .= "<tr><th>Offset</th>";
17212 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017213 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017214 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017215 {
17216 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017217
17218 my $E1 = $Entries{$Index}{"E1"};
17219 my $E2 = $Entries{$Index}{"E2"};
17220
17221 if($E1 ne $E2
17222 and $E1!~/ 0x/
17223 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017224 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017225 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017226 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017227 $Color1 = " class='failed'";
17228 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017229 }
17230 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017231 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017232 }
17233 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017234 $VTABLES .= "<tr><th>".$Index."</th>\n";
17235 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17236 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017237 }
17238 $VTABLES .= "</table><br/>\n";
17239 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017240 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 }
17242 return $VTABLES;
17243 }
17244 }
17245 return "";
17246}
17247
17248sub simpleVEntry($)
17249{
17250 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017251 if(not defined $VEntry
17252 or $VEntry eq "") {
17253 return "";
17254 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017255
17256 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17258 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17259 if($VEntry=~/\A_ZThn.+\Z/) {
17260 $VEntry = "non-virtual thunk";
17261 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017262 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017263 # support for old GCC versions
17264 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17265 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17266 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017267 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17268 return $VEntry;
17269}
17270
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017271sub adjustParamPos($$$)
17272{
17273 my ($Pos, $Symbol, $LibVersion) = @_;
17274 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17275 {
17276 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17277 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17278 {
17279 return $Pos-1;
17280 }
17281
17282 return $Pos;
17283 }
17284
17285 return undef;
17286}
17287
17288sub getParamPos($$$)
17289{
17290 my ($Name, $Symbol, $LibVersion) = @_;
17291
17292 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17293 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17294 {
17295 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17296 foreach (keys(%{$Info->{"Param"}}))
17297 {
17298 if($Info->{"Param"}{$_}{"name"} eq $Name)
17299 {
17300 return $_;
17301 }
17302 }
17303 }
17304
17305 return undef;
17306}
17307
17308sub getParamName($)
17309{
17310 my $Loc = $_[0];
17311 $Loc=~s/\->.*//g;
17312 return $Loc;
17313}
17314
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017315sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017316{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017317 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017318
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017319 my $LIMIT = 10;
17320 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017321 $LIMIT = $AffectLimit;
17322 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017323
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017324 my @Kinds = sort keys(%{$Kinds_Locations});
17325 my %KLocs = ();
17326 foreach my $Kind (@Kinds)
17327 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017328 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 +030017329 $KLocs{$Kind} = \@Locs;
17330 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017331
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017332 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017333 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017335 if(index($Symbol, "_Z")==0
17336 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017337 { # duplicated problems for C2 constructors, D2 and D0 destructors
17338 next;
17339 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017340
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017341 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017342 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017343 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017344 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017345 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017346 next;
17347 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017348
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017349 if(index($Symbol, "\@")!=-1
17350 or index($Symbol, "\$")!=-1)
17351 {
17352 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17353
17354 if($Level eq "Source")
17355 { # remove symbol version
17356 $Symbol = $SN;
17357 }
17358
17359 if($SV and defined $CompatProblems{$Level}{$SN}
17360 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17361 { # duplicated problems for versioned symbols
17362 next;
17363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017364 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017365
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017366 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017367 if($Type_Name ne $Target_TypeName) {
17368 next;
17369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017371 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017372 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017373 }
17374 }
17375 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017376
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017377 %KLocs = (); # clear
17378
17379 my %SymSel = ();
17380 my $Num = 0;
17381 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017382 {
17383 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17384 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017385 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017386 {
17387 $SymSel{$Symbol}{"Loc"} = $Loc;
17388 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017389 last LOOP;
17390 }
17391 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017392
17393 $Num += 1;
17394
17395 if($Num>=$LIMIT) {
17396 last;
17397 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017398 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017399
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017400 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017402 if($ReportFormat eq "xml")
17403 { # XML
17404 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017405
17406 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017407 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017408 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017409 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017410 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017413 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017414 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017415 $Target .= " param=\"$PName\"";
17416 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017417 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017418 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017419 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017420 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017421 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017422 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017423 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017424
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017425 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017426 $Target .= " field=\"$1\"";
17427 }
17428
17429 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017430 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017431 $Affected .= " </symbol>\n";
17432 }
17433 $Affected .= " </affected>\n";
17434 }
17435 else
17436 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017437 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017438 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017439 my $Kind = $SymSel{$Symbol}{"Kind"};
17440 my $Loc = $SymSel{$Symbol}{"Loc"};
17441
17442 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017443 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017444 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017445 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17446
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017447 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017448 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017449 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017450
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017451 if(keys(%SymLocKind)>$LIMIT) {
17452 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017453 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017454
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017455 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017456 if($Affected)
17457 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017458 my $Num = keys(%SymLocKind);
17459 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017460 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017461 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017462 }
17463 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 return $Affected;
17466}
17467
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017468sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017469{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017470 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017471 if($L2=~/\A(retval|this)\b/
17472 and $L1!~/\A(retval|this)\b/)
17473 {
17474 if($L1!~/\-\>/) {
17475 return 1;
17476 }
17477 elsif($L2=~/\-\>/) {
17478 return 1;
17479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017480 }
17481 return 0;
17482}
17483
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017484sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017485{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017486 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017487
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017488 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017489
17490 my $Location_I = $Location;
17491 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17492
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017493 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017494
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017495 if($Kind eq "Overridden_Virtual_Method"
17496 or $Kind eq "Overridden_Virtual_Method_B") {
17497 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17498 }
17499 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17500 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017501 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17502
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017503 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17504 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017505 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17506 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17507
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017508 if($ClassName eq $Problem{"Type_Name"}) {
17509 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17510 }
17511 else {
17512 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17513 }
17514 }
17515 else
17516 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017517 my $TypeID = undef;
17518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017519 if($Location=~/retval/)
17520 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017521 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017522 push(@Sentence, "Field \'".$Location."\' in return value");
17523 }
17524 else {
17525 push(@Sentence, "Return value");
17526 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017527
17528 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017529 }
17530 elsif($Location=~/this/)
17531 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017532 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017533 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17534 }
17535 else {
17536 push(@Sentence, "\'this\' pointer");
17537 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017538
17539 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017540 }
17541 else
17542 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017543
17544 my $PName = getParamName($Location);
17545 my $PPos = getParamPos($PName, $Symbol, 1);
17546
17547 if(index($Location, "->")!=-1) {
17548 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017549 }
17550 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017551 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017553 if($PName) {
17554 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017555 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017556
17557 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17558 }
17559
17560 if($Location!~/this/)
17561 {
17562 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017563 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017564 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017565 push(@Sentence, "(pointer)");
17566 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017567 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017568 push(@Sentence, "(reference)");
17569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017570 }
17571 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017573 if($Location eq "this") {
17574 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17575 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017576 else
17577 {
17578 my $Location_T = $Location;
17579 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17580
17581 my $TypeID_Problem = $TypeID;
17582 if($Location_T) {
17583 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17584 }
17585
17586 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17587 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17588 }
17589 else {
17590 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017592 }
17593 }
17594 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017595 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017596 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 +040017597 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017598
17599 my $Sent = join(" ", @Sentence);
17600
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017601 $Sent=~s/->/./g;
17602
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017603 if($ReportFormat eq "xml")
17604 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017605 $Sent=~s/'//g;
17606 }
17607
17608 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017609}
17610
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017611sub getFieldType($$$)
17612{
17613 my ($Location, $TypeId, $LibVersion) = @_;
17614
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017615 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017616
17617 foreach my $Name (@Fields)
17618 {
17619 my %Info = get_BaseType($TypeId, $LibVersion);
17620
17621 foreach my $Pos (keys(%{$Info{"Memb"}}))
17622 {
17623 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17624 {
17625 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17626 last;
17627 }
17628 }
17629 }
17630
17631 return $TypeId;
17632}
17633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017634sub get_XmlSign($$)
17635{
17636 my ($Symbol, $LibVersion) = @_;
17637 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17638 my $Report = "";
17639 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17640 {
17641 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017642 my $Type = $Info->{"Param"}{$Pos}{"type"};
17643 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017644 foreach my $Typedef (keys(%ChangedTypedef))
17645 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017646 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17647 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17648 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017649 }
17650 $Report .= " <param pos=\"$Pos\">\n";
17651 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017652 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017653 $Report .= " </param>\n";
17654 }
17655 if(my $Return = $Info->{"Return"})
17656 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017657 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017658 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017659 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017660 $Report .= " </retval>\n";
17661 }
17662 return $Report;
17663}
17664
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017665sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017666{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017667 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017668 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017669 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017670 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017671 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17672 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017673 next;
17674 }
17675 $Report .= " <symbol name=\"$Symbol\">\n";
17676 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017677 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017678 {
17679 if(defined $CompleteSignature{1}{$Symbol}
17680 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17681 {
17682 $P1 = get_XmlSign($Symbol, 1);
17683 $S1 = get_Signature($Symbol, 1);
17684 }
17685 elsif($Symbol=~/\A(_Z|\?)/) {
17686 $S1 = $tr_name{$Symbol};
17687 }
17688 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017689 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017690 {
17691 if(defined $CompleteSignature{2}{$Symbol}
17692 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17693 {
17694 $P2 = get_XmlSign($Symbol, 2);
17695 $S2 = get_Signature($Symbol, 2);
17696 }
17697 elsif($Symbol=~/\A(_Z|\?)/) {
17698 $S2 = $tr_name{$Symbol};
17699 }
17700 }
17701 if($S1)
17702 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017703 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017704 $Report .= $P1;
17705 $Report .= " </old>\n";
17706 }
17707 if($S2 and $S2 ne $S1)
17708 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017709 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017710 $Report .= $P2;
17711 $Report .= " </new>\n";
17712 }
17713 $Report .= " </symbol>\n";
17714 }
17715 $Report .= "</symbols_info>\n";
17716 return $Report;
17717}
17718
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017719sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017720{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017721 my ($Level, $Report) = @_;
17722 if($ReportFormat eq "xml") {
17723 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017724 }
17725 if($StdOut)
17726 { # --stdout option
17727 print STDOUT $Report;
17728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017729 else
17730 {
17731 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017732 mkpath(get_dirname($RPath));
17733
17734 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17735 print REPORT $Report;
17736 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017737 }
17738}
17739
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017740sub getReport($)
17741{
17742 my $Level = $_[0];
17743 if($ReportFormat eq "xml")
17744 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017745 if($Level eq "Join")
17746 {
17747 my $Report = "<reports>\n";
17748 $Report .= getReport("Binary");
17749 $Report .= getReport("Source");
17750 $Report .= "</reports>\n";
17751 return $Report;
17752 }
17753 else
17754 {
17755 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17756 my ($Summary, $MetaData) = get_Summary($Level);
17757 $Report .= $Summary."\n";
17758 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17759 $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 +040017760
17761 # additional symbols info (if needed)
17762 # $Report .= get_Report_SymbolsInfo($Level);
17763
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017764 $Report .= "</report>\n";
17765 return $Report;
17766 }
17767 }
17768 else
17769 { # HTML
17770 my $CssStyles = readModule("Styles", "Report.css");
17771 my $JScripts = readModule("Scripts", "Sections.js");
17772 if($Level eq "Join")
17773 {
17774 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17775 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017776 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017777 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17778 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 +040017779 my ($BSummary, $BMetaData) = get_Summary("Binary");
17780 my ($SSummary, $SMetaData) = get_Summary("Source");
17781 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 +030017782 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017783 <br/>
17784 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017785 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17786 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017787 </div>";
17788 $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>";
17789 $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 +030017790 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017791 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017792 return $Report;
17793 }
17794 else
17795 {
17796 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017797 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17798 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17799 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 +040017800 if($Level eq "Binary")
17801 {
17802 if(getArch(1) eq getArch(2)
17803 and getArch(1) ne "unknown") {
17804 $Description .= " on ".showArch(getArch(1));
17805 }
17806 }
17807 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 +030017808 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017809 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17810 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17811 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017812 $Report .= "</div>\n<br/><br/><br/>\n";
17813 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017814 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017815 return $Report;
17816 }
17817 }
17818}
17819
17820sub createReport()
17821{
17822 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017823 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017824 writeReport("Join", getReport("Join"));
17825 }
17826 elsif($DoubleReport)
17827 { # default
17828 writeReport("Binary", getReport("Binary"));
17829 writeReport("Source", getReport("Source"));
17830 }
17831 elsif($BinaryOnly)
17832 { # --binary
17833 writeReport("Binary", getReport("Binary"));
17834 }
17835 elsif($SourceOnly)
17836 { # --source
17837 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017838 }
17839}
17840
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017841sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017842{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017843 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017844
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017845 $Footer .= "<hr/>\n";
17846 $Footer .= "<div class='footer' align='right'>";
17847 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17848 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017849 $Footer .= "<br/>\n";
17850
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017851 return $Footer;
17852}
17853
17854sub get_Report_Problems($$)
17855{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017856 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017857
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017858 my $Report = get_Report_TypeProblems($Severity, $Level);
17859 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017860 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017861 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017862
17863 if($Severity eq "Low" or $Severity eq "Safe") {
17864 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017865 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017866
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017867 if($ReportFormat eq "html")
17868 {
17869 if($Report)
17870 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017871 if($JoinReport)
17872 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017873 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017874 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17875 }
17876 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017877 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017878 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017879 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017880 else
17881 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017882 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017883 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17884 }
17885 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017886 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017888 }
17889 }
17890 }
17891 return $Report;
17892}
17893
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017894sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017895{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017896 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030017897
17898 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
17899 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
17900 $Head .= "<head>\n";
17901 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
17902 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
17903 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
17904 $Head .= "<title>$Title</title>\n";
17905 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
17906 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
17907 $Head .= "</head>\n";
17908
17909 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017910}
17911
17912sub insertIDs($)
17913{
17914 my $Text = $_[0];
17915 while($Text=~/CONTENT_ID/)
17916 {
17917 if(int($Content_Counter)%2) {
17918 $ContentID -= 1;
17919 }
17920 $Text=~s/CONTENT_ID/c_$ContentID/;
17921 $ContentID += 1;
17922 $Content_Counter += 1;
17923 }
17924 return $Text;
17925}
17926
17927sub checkPreprocessedUnit($)
17928{
17929 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017930 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017931 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017932 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017933
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017934 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017935 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017936 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017937 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017938 chomp($Line);
17939 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017940 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017941 $CurHeader = path_format($1, $OSgroup);
17942 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017943 $CurClass = "";
17944
17945 if(index($CurHeader, $TMP_DIR)==0) {
17946 next;
17947 }
17948
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017949 if(substr($CurHeaderName, 0, 1) eq "<")
17950 { # <built-in>, <command-line>, etc.
17951 $CurHeaderName = "";
17952 $CurHeader = "";
17953 }
17954
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017955 if($ExtraInfo)
17956 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017957 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017958 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17959 }
17960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017961 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017962 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017963 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017964 if($CurHeaderName)
17965 {
17966 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17967 and not $Registered_Headers{$Version}{$CurHeader})
17968 { # not a target
17969 next;
17970 }
17971 if(not is_target_header($CurHeaderName, 1)
17972 and not is_target_header($CurHeaderName, 2))
17973 { # user-defined header
17974 next;
17975 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017976 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017977 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017978
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017979 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017980 {
17981 my ($Name, $Value) = ($1, $2);
17982 if(not $Constants{$Version}{$Name}{"Access"})
17983 {
17984 $Constants{$Version}{$Name}{"Access"} = "public";
17985 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017986 if($CurHeaderName) {
17987 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17988 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017989 }
17990 }
17991 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17992 $Constants{$Version}{$1}{"Access"} = "private";
17993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017994 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017995 else
17996 {
17997 if(defined $ExtraDump)
17998 {
17999 if($Line=~/(\w+)\s*\(/)
18000 { # functions
18001 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18002 }
18003 #elsif($Line=~/(\w+)\s*;/)
18004 #{ # data
18005 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18006 #}
18007 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18008 $CurClass = $2;
18009 }
18010 }
18011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018012 }
18013 close(PREPROC);
18014 foreach my $Constant (keys(%{$Constants{$Version}}))
18015 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018016 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18017 {
18018 delete($Constants{$Version}{$Constant});
18019 next;
18020 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018021 if(not $ExtraDump and ($Constant=~/_h\Z/i
18022 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018023 { # skip
18024 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018025 }
18026 else {
18027 delete($Constants{$Version}{$Constant}{"Access"});
18028 }
18029 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018030 if($Debug)
18031 {
18032 mkpath($DEBUG_PATH{$Version});
18033 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018035}
18036
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018037sub uncoverConstant($$)
18038{
18039 my ($LibVersion, $Constant) = @_;
18040 return "" if(not $LibVersion or not $Constant);
18041 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18042 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18043 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18044 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018045
18046 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018047 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018048 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18049 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018050 {
18051 push(@RecurConstant, $Constant);
18052 my $Uncovered = uncoverConstant($LibVersion, $Value);
18053 if($Uncovered ne "") {
18054 $Value = $Uncovered;
18055 }
18056 pop(@RecurConstant);
18057 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018058
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018059 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018060 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018061 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18062 }
18063 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18064}
18065
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018066sub simpleConstant($$)
18067{
18068 my ($LibVersion, $Value) = @_;
18069 if($Value=~/\W/)
18070 {
18071 my $Value_Copy = $Value;
18072 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18073 {
18074 my $Word = $1;
18075 if($Value!~/$Word\s*\(/)
18076 {
18077 my $Val = uncoverConstant($LibVersion, $Word);
18078 if($Val ne "")
18079 {
18080 $Value=~s/\b$Word\b/$Val/g;
18081 }
18082 }
18083 }
18084 }
18085 return $Value;
18086}
18087
18088sub computeValue($)
18089{
18090 my $Value = $_[0];
18091
18092 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18093 return $1;
18094 }
18095
18096 if($Value=~/\A[\d\-\+()]+\Z/) {
18097 return eval($Value);
18098 }
18099
18100 return $Value;
18101}
18102
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018103my %IgnoreConstant = map {$_=>1} (
18104 "VERSION",
18105 "VERSIONCODE",
18106 "VERNUM",
18107 "VERS_INFO",
18108 "PATCHLEVEL",
18109 "INSTALLPREFIX",
18110 "VBUILD",
18111 "VPATCH",
18112 "VMINOR",
18113 "BUILD_STRING",
18114 "BUILD_TIME",
18115 "PACKAGE_STRING",
18116 "PRODUCTION",
18117 "CONFIGURE_COMMAND",
18118 "INSTALLDIR",
18119 "BINDIR",
18120 "CONFIG_FILE_PATH",
18121 "DATADIR",
18122 "EXTENSION_DIR",
18123 "INCLUDE_PATH",
18124 "LIBDIR",
18125 "LOCALSTATEDIR",
18126 "SBINDIR",
18127 "SYSCONFDIR",
18128 "RELEASE",
18129 "SOURCE_ID",
18130 "SUBMINOR",
18131 "MINOR",
18132 "MINNOR",
18133 "MINORVERSION",
18134 "MAJOR",
18135 "MAJORVERSION",
18136 "MICRO",
18137 "MICROVERSION",
18138 "BINARY_AGE",
18139 "INTERFACE_AGE",
18140 "CORE_ABI",
18141 "PATCH",
18142 "COPYRIGHT",
18143 "TIMESTAMP",
18144 "REVISION",
18145 "PACKAGE_TAG",
18146 "PACKAGEDATE",
18147 "NUMVERSION",
18148 "Release",
18149 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018150);
18151
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018152sub constantFilter($$$)
18153{
18154 my ($Name, $Value, $Level) = @_;
18155
18156 if($Level eq "Binary")
18157 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018158 if($Name=~/_t\Z/)
18159 { # __malloc_ptr_t
18160 return 1;
18161 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018162 foreach (keys(%IgnoreConstant))
18163 {
18164 if($Name=~/(\A|_)$_(_|\Z)/)
18165 { # version
18166 return 1;
18167 }
18168 if(/\A[A-Z].*[a-z]\Z/)
18169 {
18170 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18171 { # version
18172 return 1;
18173 }
18174 }
18175 }
18176 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18177 { # version
18178 return 1;
18179 }
18180 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18181 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18182 return 1;
18183 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018184
18185 if($Value=~/\A["'].*['"]/i)
18186 { # string
18187 return 0;
18188 }
18189
18190 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18191 { # static int gcry_pth_init
18192 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018193 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018194 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018195 return 1;
18196 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018197 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018198 { # foo(p)
18199 return 1;
18200 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018201 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018202 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018203 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018204 return 1;
18205 }
18206 }
18207
18208 return 0;
18209}
18210
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018211sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018212{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018213 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018214 foreach my $Constant (keys(%{$Constants{1}}))
18215 {
18216 if($SkipConstants{1}{$Constant})
18217 { # skipped by the user
18218 next;
18219 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018220
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018221 if(my $Header = $Constants{1}{$Constant}{"Header"})
18222 {
18223 if(not is_target_header($Header, 1)
18224 and not is_target_header($Header, 2))
18225 { # user-defined header
18226 next;
18227 }
18228 }
18229 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018230 next;
18231 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018232
18233 my $Old_Value = uncoverConstant(1, $Constant);
18234
18235 if(constantFilter($Constant, $Old_Value, $Level))
18236 { # separate binary and source problems
18237 next;
18238 }
18239
18240 if(not defined $Constants{2}{$Constant}{"Value"})
18241 { # removed
18242 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18243 "Target"=>$Constant,
18244 "Old_Value"=>$Old_Value );
18245 next;
18246 }
18247
18248 if($Constants{2}{$Constant}{"Value"} eq "")
18249 { # empty value
18250 # TODO: implement a rule
18251 next;
18252 }
18253
18254 my $New_Value = uncoverConstant(2, $Constant);
18255
18256 my $Old_Value_Pure = $Old_Value;
18257 my $New_Value_Pure = $New_Value;
18258
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018259 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18260 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18261 $New_Value_Pure=~s/(\W)\s+/$1/g;
18262 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018263
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018264 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018265
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018266 if($New_Value_Pure ne $Old_Value_Pure)
18267 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018268 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18269 { # complex values
18270 next;
18271 }
18272 if(computeValue($Old_Value) eq computeValue($New_Value))
18273 { # expressions
18274 next;
18275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018276 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18277 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18278 next;
18279 }
18280 if($Old_Value eq "0" and $New_Value eq "NULL")
18281 { # 0 => NULL
18282 next;
18283 }
18284 if($Old_Value eq "NULL" and $New_Value eq "0")
18285 { # NULL => 0
18286 next;
18287 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018288 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018289 "Target"=>$Constant,
18290 "Old_Value"=>$Old_Value,
18291 "New_Value"=>$New_Value );
18292 }
18293 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018294
18295 foreach my $Constant (keys(%{$Constants{2}}))
18296 {
18297 if(not defined $Constants{1}{$Constant}{"Value"})
18298 {
18299 if($SkipConstants{2}{$Constant})
18300 { # skipped by the user
18301 next;
18302 }
18303
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018304 if(my $Header = $Constants{2}{$Constant}{"Header"})
18305 {
18306 if(not is_target_header($Header, 1)
18307 and not is_target_header($Header, 2))
18308 { # user-defined header
18309 next;
18310 }
18311 }
18312 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018313 next;
18314 }
18315
18316 my $New_Value = uncoverConstant(2, $Constant);
18317 if(not defined $New_Value or $New_Value eq "") {
18318 next;
18319 }
18320
18321 if(constantFilter($Constant, $New_Value, $Level))
18322 { # separate binary and source problems
18323 next;
18324 }
18325
18326 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18327 "Target"=>$Constant,
18328 "New_Value"=>$New_Value );
18329 }
18330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018331}
18332
18333sub convert_integer($)
18334{
18335 my $Value = $_[0];
18336 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018337 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018338 return hex($Value);
18339 }
18340 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018341 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018342 return oct($Value);
18343 }
18344 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018345 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018346 return oct($Value);
18347 }
18348 else {
18349 return $Value;
18350 }
18351}
18352
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018353sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018354{
18355 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018356 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018357 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018358 {
18359 if($LibVersion==1)
18360 {
18361 printMsg("WARNING", "checking headers only");
18362 $CheckHeadersOnly = 1;
18363 }
18364 else {
18365 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18366 }
18367 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018368
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018369 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018370 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018371 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018372
18373 if($CheckUndefined)
18374 {
18375 my %UndefinedLibs = ();
18376
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018377 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18378
18379 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018380 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018381 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018382 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018383 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018384 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018385 if($Symbol_Library{$LibVersion}{$Symbol}
18386 or $DepSymbol_Library{$LibVersion}{$Symbol})
18387 { # exported by target library
18388 next;
18389 }
18390 if(index($Symbol, '@')!=-1)
18391 { # exported default symbol version (@@)
18392 $Symbol=~s/\@/\@\@/;
18393 if($Symbol_Library{$LibVersion}{$Symbol}
18394 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18395 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018396 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018397 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018398 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18399 $UndefinedLibs{$Path} = 1;
18400 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018401 }
18402 }
18403 }
18404 if($ExtraInfo)
18405 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018406 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018407 {
18408 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018409 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018410 foreach (@Paths)
18411 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018412 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018413 my ($Dir, $Name) = separate_path($_);
18414
18415 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018416 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018417 }
18418
18419 $Name = parse_libname($Name, "name", $OStarget);
18420 $Name=~s/\Alib//;
18421
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018422 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018423 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018424
18425 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18426 {
18427 $LibString = " -L".esc($Dir).$LibString;
18428 }
18429
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018430 writeFile($ExtraInfo."/libs-string", $LibString);
18431 }
18432 }
18433 }
18434
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018435 if($ExtraInfo) {
18436 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18437 }
18438
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018439 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018440 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018441 if($#LibPaths!=-1)
18442 {
18443 if(not keys(%{$Symbol_Library{$LibVersion}}))
18444 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018445 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018446 printMsg("WARNING", "checking headers only");
18447 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018448 }
18449 }
18450 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018451
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018452 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018453 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018454}
18455
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018456my %Prefix_Lib_Map=(
18457 # symbols for autodetecting library dependencies (by prefix)
18458 "pthread_" => ["libpthread"],
18459 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18460 "cairo_" => ["libcairo"],
18461 "gtk_" => ["libgtk-x11-2.0"],
18462 "atk_" => ["libatk-1.0"],
18463 "gdk_" => ["libgdk-x11-2.0"],
18464 "gl" => ["libGL"],
18465 "glu" => ["libGLU"],
18466 "popt" => ["libpopt"],
18467 "Py" => ["libpython"],
18468 "jpeg_" => ["libjpeg"],
18469 "BZ2_" => ["libbz2"],
18470 "Fc" => ["libfontconfig"],
18471 "Xft" => ["libXft"],
18472 "SSL_" => ["libssl"],
18473 "sem_" => ["libpthread"],
18474 "snd_" => ["libasound"],
18475 "art_" => ["libart_lgpl_2"],
18476 "dbus_g" => ["libdbus-glib-1"],
18477 "GOMP_" => ["libgomp"],
18478 "omp_" => ["libgomp"],
18479 "cms" => ["liblcms"]
18480);
18481
18482my %Pattern_Lib_Map=(
18483 "SL[a-z]" => ["libslang"]
18484);
18485
18486my %Symbol_Lib_Map=(
18487 # symbols for autodetecting library dependencies (by name)
18488 "pow" => "libm",
18489 "fmod" => "libm",
18490 "sin" => "libm",
18491 "floor" => "libm",
18492 "cos" => "libm",
18493 "dlopen" => "libdl",
18494 "deflate" => "libz",
18495 "inflate" => "libz",
18496 "move_panel" => "libpanel",
18497 "XOpenDisplay" => "libX11",
18498 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018499 "clock_gettime" => "librt",
18500 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018501);
18502
18503sub find_SymbolLibs($$)
18504{
18505 my ($LibVersion, $Symbol) = @_;
18506
18507 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18508 { # debug symbols
18509 return ();
18510 }
18511
18512 my %Paths = ();
18513
18514 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18515 {
18516 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18517 $Paths{$Path} = 1;
18518 }
18519 }
18520
18521 if(my $SymbolPrefix = getPrefix($Symbol))
18522 {
18523 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18524 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18525 }
18526
18527 if(not keys(%Paths))
18528 {
18529 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18530 {
18531 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18532 {
18533 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18534 $Paths{$Path} = 1;
18535 }
18536 }
18537 }
18538 }
18539
18540 if(not keys(%Paths))
18541 {
18542 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18543 {
18544 if($Symbol=~/\A$Prefix/)
18545 {
18546 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18547 {
18548 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18549 $Paths{$Path} = 1;
18550 }
18551 }
18552 }
18553 }
18554 }
18555
18556 if(not keys(%Paths))
18557 {
18558 if($SymbolPrefix)
18559 { # try to find a library by symbol prefix
18560 if($SymbolPrefix eq "inotify" and
18561 index($Symbol, "\@GLIBC")!=-1)
18562 {
18563 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18564 $Paths{$Path} = 1;
18565 }
18566 }
18567 else
18568 {
18569 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18570 $Paths{$Path} = 1;
18571 }
18572 }
18573 }
18574 }
18575
18576 if(my @Paths = keys(%Paths)) {
18577 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18578 }
18579 }
18580 return keys(%Paths);
18581}
18582
18583sub get_LibPath_Prefix($$)
18584{
18585 my ($LibVersion, $Prefix) = @_;
18586
18587 $Prefix = lc($Prefix);
18588 $Prefix=~s/[_]+\Z//g;
18589
18590 foreach ("-2", "2", "-1", "1", "")
18591 { # libgnome-2.so
18592 # libxml2.so
18593 # libdbus-1.so
18594 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18595 return $Path;
18596 }
18597 }
18598 return "";
18599}
18600
18601sub getPrefix($)
18602{
18603 my $Str = $_[0];
18604 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18605 { # XmuValidArea: Xmu
18606 return $1;
18607 }
18608 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18609 { # snfReadFont: snf
18610 return $1;
18611 }
18612 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18613 { # XRRTimes: XRR
18614 return $1;
18615 }
18616 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18617 { # H5HF_delete: H5
18618 return $1;
18619 }
18620 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18621 { # alarm_event_add: alarm_
18622 return $1;
18623 }
18624 elsif($Str=~/\A(([a-z])\2{1,})/i)
18625 { # ffopen
18626 return $1;
18627 }
18628 return "";
18629}
18630
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018631sub getSymbolSize($$)
18632{ # size from the shared library
18633 my ($Symbol, $LibVersion) = @_;
18634 return 0 if(not $Symbol);
18635 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18636 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18637 {
18638 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18639 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18640 {
18641 if($Size<0) {
18642 return -$Size;
18643 }
18644 }
18645 }
18646 return 0;
18647}
18648
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018649sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018650{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18651 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018652 my ($Name, $Type) = @_;
18653
18654 # single
18655 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018656 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018657 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018658 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018659 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018660
18661 # double
18662 if($Name=~/$DEFAULT_STD_PARMS/)
18663 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018664 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018665 {
18666 my ($ShortName, $FuncParams) = split_Signature($Name);
18667
18668 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18669 {
18670 if(index($FParam, "<")!=-1)
18671 {
18672 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18673 my $FParam_N = canonifyName($FParam, "T");
18674 if($FParam_N ne $FParam) {
18675 $Name=~s/\Q$FParam\E/$FParam_N/g;
18676 }
18677 }
18678 }
18679 }
18680 elsif($Type eq "T")
18681 {
18682 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18683
18684 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018685 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018686 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018687 my $FParam = $TParams[0];
18688 foreach my $Pos (1 .. $#TParams)
18689 {
18690 my $TParam = $TParams[$Pos];
18691 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18692 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18693 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018694 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018695 }
18696 }
18697 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018698 if($Type eq "S") {
18699 return formatName($Name, "S");
18700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018701 return $Name;
18702}
18703
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018704sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018705{
18706 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018707 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018708 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018709 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018710 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018711 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018712 next if($tr_name{$Symbol});
18713 $Symbol=~s/[\@\$]+(.*)\Z//;
18714 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018715 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018716 elsif(index($Symbol, "?")==0)
18717 {
18718 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018719 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018720 }
18721 else
18722 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018723 $tr_name{$Symbol} = $Symbol;
18724 $mangled_name_gcc{$Symbol} = $Symbol;
18725 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018726 }
18727 }
18728 if($#MnglNames1 > -1)
18729 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018730 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018731 foreach my $MnglName (@MnglNames1)
18732 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018733 if(my $Unmangled = pop(@UnmangledNames))
18734 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018735 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018736 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18737 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18738 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018739 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018740 and $tr_name{$MnglName}=~/vtable for (.+)/)
18741 { # bind class name and v-table symbol
18742 my $ClassName = $1;
18743 $ClassVTable{$ClassName} = $MnglName;
18744 $VTableClass{$MnglName} = $ClassName;
18745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018746 }
18747 }
18748 }
18749 if($#MnglNames2 > -1)
18750 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018751 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018752 foreach my $MnglName (@MnglNames2)
18753 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018754 if(my $Unmangled = pop(@UnmangledNames))
18755 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018756 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018757 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018759 }
18760 }
18761 return \%tr_name;
18762}
18763
18764sub link_symbol($$$)
18765{
18766 my ($Symbol, $RunWith, $Deps) = @_;
18767 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18768 return 1;
18769 }
18770 if($Deps eq "+Deps")
18771 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018772 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018773 return 1;
18774 }
18775 }
18776 return 0;
18777}
18778
18779sub link_symbol_internal($$$)
18780{
18781 my ($Symbol, $RunWith, $Where) = @_;
18782 return 0 if(not $Where or not $Symbol);
18783 if($Where->{$RunWith}{$Symbol})
18784 { # the exact match by symbol name
18785 return 1;
18786 }
18787 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18788 { # indirect symbol version, i.e.
18789 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018790 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018791 if($Where->{$RunWith}{$VSym}) {
18792 return 1;
18793 }
18794 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018795 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018796 if($Sym and $Ver)
18797 { # search for the symbol with the same version
18798 # or without version
18799 if($Where->{$RunWith}{$Sym})
18800 { # old: foo@v|foo@@v
18801 # new: foo
18802 return 1;
18803 }
18804 if($Where->{$RunWith}{$Sym."\@".$Ver})
18805 { # old: foo|foo@@v
18806 # new: foo@v
18807 return 1;
18808 }
18809 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18810 { # old: foo|foo@v
18811 # new: foo@@v
18812 return 1;
18813 }
18814 }
18815 return 0;
18816}
18817
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018818sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018819{
18820 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018821 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018822 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018823 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018824 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018825 my $NM = get_CmdPath("nm");
18826 if(not $NM) {
18827 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018828 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018829 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018830 while(<APP>)
18831 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018832 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018833 push(@Imported, $1);
18834 }
18835 }
18836 close(APP);
18837 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018838 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018839 {
18840 my $DumpBinCmd = get_CmdPath("dumpbin");
18841 if(not $DumpBinCmd) {
18842 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18843 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018844 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018845 while(<APP>)
18846 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18848 push(@Imported, $1);
18849 }
18850 }
18851 close(APP);
18852 }
18853 else
18854 {
18855 my $ReadelfCmd = get_CmdPath("readelf");
18856 if(not $ReadelfCmd) {
18857 exitStatus("Not_Found", "can't find \"readelf\"");
18858 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018859 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018860 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018861 while(<APP>)
18862 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018863 if(defined $symtab)
18864 { # do nothing with symtab
18865 if(index($_, "'.dynsym'")!=-1)
18866 { # dynamic table
18867 $symtab = undef;
18868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018869 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018870 elsif(index($_, "'.symtab'")!=-1)
18871 { # symbol table
18872 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018873 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018874 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018875 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018876 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18877 if($Ndx eq "UND")
18878 { # only imported symbols
18879 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018880 }
18881 }
18882 }
18883 close(APP);
18884 }
18885 return @Imported;
18886}
18887
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018888my %ELF_BIND = map {$_=>1} (
18889 "WEAK",
18890 "GLOBAL"
18891);
18892
18893my %ELF_TYPE = map {$_=>1} (
18894 "FUNC",
18895 "IFUNC",
18896 "OBJECT",
18897 "COMMON"
18898);
18899
18900my %ELF_VIS = map {$_=>1} (
18901 "DEFAULT",
18902 "PROTECTED"
18903);
18904
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018905sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018906{ # read the line of 'readelf' output corresponding to the symbol
18907 my @Info = split(/\s+/, $_[0]);
18908 # Num: Value Size Type Bind Vis Ndx Name
18909 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018910 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018911 shift(@Info); # spaces
18912 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018913
18914 if($#Info==7)
18915 { # UND SYMBOL (N)
18916 if($Info[7]=~/\(\d+\)/) {
18917 pop(@Info);
18918 }
18919 }
18920
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018921 if($#Info!=6)
18922 { # other lines
18923 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018924 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018925 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018926 return () if(not defined $ELF_BIND{$Info[3]});
18927 return () if(not defined $ELF_VIS{$Info[4]});
18928 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18929 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18930 return ();
18931 }
18932 if($OStarget eq "symbian")
18933 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18934 if(index($Info[6], "_._.absent_export_")!=-1)
18935 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18936 return ();
18937 }
18938 $Info[6]=~s/\@.+//g; # remove version
18939 }
18940 if(index($Info[2], "0x") == 0)
18941 { # size == 0x3d158
18942 $Info[2] = hex($Info[2]);
18943 }
18944 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018945}
18946
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018947sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018948{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018949 my ($LibVersion, $Name) = @_;
18950 return "" if(not $LibVersion or not $Name);
18951 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18952 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018953 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018954 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18955}
18956
18957sub get_LibPath_I($$)
18958{
18959 my ($LibVersion, $Name) = @_;
18960 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018961 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018962 if(-f $Name)
18963 { # absolute path
18964 return $Name;
18965 }
18966 else
18967 { # broken
18968 return "";
18969 }
18970 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018971 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018972 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018973 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018974 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018975 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018976 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018977 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018978 }
18979 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18980 { # ldconfig default paths
18981 return $DefaultPath;
18982 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018983 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018984 { # search in default linker directories
18985 # and then in all system paths
18986 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018987 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018988 }
18989 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018990 if(not defined $Cache{"checkSystemFiles"}) {
18991 checkSystemFiles();
18992 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018993 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18994 return $AllObjects[0];
18995 }
18996 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18997 {
18998 if($ShortName ne $Name)
18999 { # FIXME: check this case
19000 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19001 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019002 }
19003 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019004 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019005 # can't find
19006 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019007}
19008
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019009sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019010{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019011 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19012 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019013
19014 my $Real_Path = realpath($Lib_Path);
19015
19016 if(not $Real_Path)
19017 { # broken link
19018 return ();
19019 }
19020
19021 my $Lib_Name = get_filename($Real_Path);
19022
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019023 if($ExtraInfo)
19024 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019025 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019026 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019027 }
19028
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019029 if($IsNeededLib)
19030 {
19031 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19032 return ();
19033 }
19034 }
19035 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019036 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019037
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019038 push(@RecurLib, $Lib_Name);
19039 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019040 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19041
19042 if(not $IsNeededLib)
19043 { # special cases: libstdc++ and libc
19044 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19045 {
19046 if($ShortName eq "libstdc++")
19047 { # libstdc++.so.6
19048 $STDCXX_TESTING = 1;
19049 }
19050 elsif($ShortName eq "libc")
19051 { # libc-2.11.3.so
19052 $GLIBC_TESTING = 1;
19053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019054 }
19055 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019056 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019057 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019058 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019059 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019060 mkpath(get_dirname($DebugPath));
19061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019062 if($OStarget eq "macos")
19063 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019064 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019065 if(not $NM) {
19066 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019067 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019068 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019069 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019070 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019071 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019072 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019073 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019074 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019075 else
19076 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019077 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019079 while(<LIB>)
19080 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019081 if($CheckUndefined)
19082 {
19083 if(not $IsNeededLib)
19084 {
19085 if(/ U _([\w\$]+)\s*\Z/)
19086 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019087 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019088 next;
19089 }
19090 }
19091 }
19092
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019093 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019094 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019095 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019096 if($IsNeededLib)
19097 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019098 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019099 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019100 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19101 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019104 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019105 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019106 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19107 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019108 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19109 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019110 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019111 setLanguage($LibVersion, "C++");
19112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019114 }
19115 }
19116 }
19117 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019118
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019119 if($Deps)
19120 {
19121 if($LIB_TYPE eq "dynamic")
19122 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019123
19124 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019125 if(not $OtoolCmd) {
19126 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019127 }
19128
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019129 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19130 while(<LIB>)
19131 {
19132 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19133 and $1 ne $Lib_Path) {
19134 $NeededLib{$1} = 1;
19135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019136 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019137 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019139 }
19140 }
19141 elsif($OStarget eq "windows")
19142 { # Windows *.dll, *.lib
19143 my $DumpBinCmd = get_CmdPath("dumpbin");
19144 if(not $DumpBinCmd) {
19145 exitStatus("Not_Found", "can't find \"dumpbin\"");
19146 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019147 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019148 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019149 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019150 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019151 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019152 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019153 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019154 else
19155 { # write to pipe
19156 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019157 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019158 while(<LIB>)
19159 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19160 # 1198 4AD SetThreadToken (forwarded to ...)
19161 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019162 # 1 0 00005B30 ??0?N = ... (with pdb)
19163 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019164 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019165 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019166 { # dynamic, static and forwarded symbols
19167 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019168 if($IsNeededLib)
19169 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019170 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019171 {
19172 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19173 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019175 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019176 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019177 {
19178 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19179 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019180 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19181 {
19182 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19183 setLanguage($LibVersion, "C++");
19184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019185 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019186 }
19187 }
19188 }
19189 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019190
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019191 if($Deps)
19192 {
19193 if($LIB_TYPE eq "dynamic")
19194 { # dependencies
19195 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19196 while(<LIB>)
19197 {
19198 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19199 and $1 ne $Lib_Path) {
19200 $NeededLib{path_format($1, $OSgroup)} = 1;
19201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019202 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019203 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019205 }
19206 }
19207 else
19208 { # Unix; *.so, *.a
19209 # Symbian: *.dso, *.lib
19210 my $ReadelfCmd = get_CmdPath("readelf");
19211 if(not $ReadelfCmd) {
19212 exitStatus("Not_Found", "can't find \"readelf\"");
19213 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019214 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019215 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019216 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019217 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019218 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019219 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019220 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019221 else
19222 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019223 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019224 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019225 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226 while(<LIB>)
19227 {
19228 if($LIB_TYPE eq "dynamic")
19229 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019230 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019231 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019232 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019233 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019234 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019235 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019236 # do nothing with symtab
19237 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019238 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019239 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019240 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019241 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 next;
19243 }
19244 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019245 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019246 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019247 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019248 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019249 if($CheckUndefined)
19250 {
19251 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019252 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019253 }
19254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019255 next;
19256 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019257 if($Bind eq "WEAK")
19258 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019259 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019260 if($Weak eq "-Weak")
19261 { # skip WEAK symbols
19262 next;
19263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019264 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019265 my $Short = $Symbol;
19266 $Short=~s/\@.+//g;
19267 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019268 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019269 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19270 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019271 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019272 if($IsNeededLib)
19273 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019274 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019275 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019276 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19277 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019279 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019280 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019281 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019282 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19283 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19284 if($Vers)
19285 {
19286 if($LIB_EXT eq "so")
19287 { # value
19288 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19289 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019291 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019292 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19293 {
19294 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19295 setLanguage($LibVersion, "C++");
19296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019298 }
19299 }
19300 }
19301 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019302
19303 if($Deps and $LIB_TYPE eq "dynamic")
19304 { # dynamic library specifics
19305 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19306 open(LIB, $Cmd." |");
19307
19308 while(<LIB>)
19309 {
19310 if(/NEEDED.+\[([^\[\]]+)\]/)
19311 { # dependencies:
19312 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19313 $NeededLib{$1} = 1;
19314 }
19315 }
19316
19317 close(LIB);
19318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019319 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019320 if($Vers)
19321 {
19322 if(not $IsNeededLib and $LIB_EXT eq "so")
19323 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019324 my %Found = ();
19325
19326 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019327 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019328 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019329 next if(index($Symbol,"\@")==-1);
19330 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019331 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019332 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019333 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019334 if($Symbol_SameValue ne $Symbol
19335 and index($Symbol_SameValue,"\@")==-1)
19336 {
19337 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019338 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019339 last;
19340 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019341 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019342 }
19343 }
19344
19345 # default
19346 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19347 {
19348 next if(defined $Found{$Symbol});
19349 next if(index($Symbol,"\@\@")==-1);
19350
19351 if($Symbol=~/\A([^\@]*)\@\@/
19352 and not $SymVer{$LibVersion}{$1})
19353 {
19354 $SymVer{$LibVersion}{$1} = $Symbol;
19355 $Found{$Symbol} = 1;
19356 }
19357 }
19358
19359 # non-default
19360 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19361 {
19362 next if(defined $Found{$Symbol});
19363 next if(index($Symbol,"\@")==-1);
19364
19365 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19366 and not $SymVer{$LibVersion}{$1})
19367 {
19368 $SymVer{$LibVersion}{$1} = $Symbol;
19369 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019370 }
19371 }
19372 }
19373 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019374 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019375 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019376 foreach my $DyLib (sort keys(%NeededLib))
19377 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019378 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19379
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019380 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19381 {
19382 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19383 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19384 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019386 }
19387 }
19388 pop(@RecurLib);
19389 return $Library_Symbol{$LibVersion};
19390}
19391
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019392sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019393{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019394 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019395 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019396 return keys(%Prefixes);
19397}
19398
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019399sub get_prefixes_I($$)
19400{
19401 foreach my $P (@{$_[0]})
19402 {
19403 my @Parts = reverse(split(/[\/\\]+/, $P));
19404 my $Name = $Parts[0];
19405 foreach (1 .. $#Parts)
19406 {
19407 $_[1]->{$Name}{$P} = 1;
19408 last if($_>4 or $Parts[$_] eq "include");
19409 $Name = $Parts[$_].$SLASH.$Name;
19410 }
19411 }
19412}
19413
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019414sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019415{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019416 $Cache{"checkSystemFiles"} = 1;
19417
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019418 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019419
19420 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019421 {
19422 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019423
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019424 my @Files = cmd_find($DevelPath,"f");
19425 foreach my $Link (cmd_find($DevelPath,"l"))
19426 { # add symbolic links
19427 if(-f $Link) {
19428 push(@Files, $Link);
19429 }
19430 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019431
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019432 # search for headers in /usr/lib
19433 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19434 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19435 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019436
19437 # search for libraries in /usr/lib (including symbolic links)
19438 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19439 foreach my $Path (@Libs)
19440 {
19441 my $N = get_filename($Path);
19442 $SystemObjects{$N}{$Path} = 1;
19443 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 }
19445 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019446
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019447 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019448 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019449 next if(not -d $DevelPath);
19450 # search for all header files in the /usr/include
19451 # with or without extension (ncurses.h, QtCore, ...)
19452 push(@SysHeaders, cmd_find($DevelPath,"f"));
19453 foreach my $Link (cmd_find($DevelPath,"l"))
19454 { # add symbolic links
19455 if(-f $Link) {
19456 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019458 }
19459 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019460 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019461}
19462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019463sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019464{
19465 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019466 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019467 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19468 {
19469 if(not -e $Dest) {
19470 exitStatus("Access_Error", "can't access \'$Dest\'");
19471 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019472 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019473 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19474 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019475 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019476 }
19477 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019478 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019479}
19480
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019481sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019482{
19483 my ($Path, $LibVersion) = @_;
19484 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019485 my $Name = get_filename($Path);
19486 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019487 return 1;
19488 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019489 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019490 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19491 return 1;
19492 }
19493 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19494 {
19495 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19496 return 1;
19497 }
19498 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019499 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019500 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019501 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019502 return 1;
19503 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019504 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019505 return 1;
19506 }
19507 }
19508 return 0;
19509}
19510
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019511sub specificHeader($$)
19512{
19513 my ($Header, $Spec) = @_;
19514 my $Name = get_filename($Header);
19515
19516 if($Spec eq "windows")
19517 {# MS Windows
19518 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19519 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19520 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19521 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19522 my @Dirs = (
19523 "win32",
19524 "win64",
19525 "win",
19526 "windows",
19527 "msvcrt"
19528 ); # /gsf-win32/
19529 if(my $DIRs = join("|", @Dirs)) {
19530 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19531 }
19532 }
19533 elsif($Spec eq "macos")
19534 { # Mac OS
19535 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19536 }
19537
19538 return 0;
19539}
19540
19541sub skipAlienHeader($)
19542{
19543 my $Path = $_[0];
19544 my $Name = get_filename($Path);
19545 my $Dir = get_dirname($Path);
19546
19547 if($Tolerance=~/2/)
19548 { # 2 - skip internal headers
19549 my @Terms = (
19550 "p",
19551 "priv",
19552 "int",
19553 "impl",
19554 "implementation",
19555 "internal",
19556 "private",
19557 "old",
19558 "compat",
19559 "debug",
19560 "test",
19561 "gen"
19562 );
19563
19564 my @Dirs = (
19565 "private",
19566 "priv",
19567 "port",
19568 "impl",
19569 "internal",
19570 "detail",
19571 "details",
19572 "old",
19573 "compat",
19574 "debug",
19575 "config",
19576 "compiler",
19577 "platform",
19578 "test"
19579 );
19580
19581 if(my $TERMs = join("|", @Terms)) {
19582 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19583 }
19584 if(my $DIRs = join("|", @Dirs)) {
19585 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19586 }
19587
19588 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19589 }
19590
19591 if($Tolerance=~/1/)
19592 { # 1 - skip non-Linux headers
19593 if($OSgroup ne "windows")
19594 {
19595 if(specificHeader($Path, "windows")) {
19596 return 1;
19597 }
19598 }
19599 if($OSgroup ne "macos")
19600 {
19601 if(specificHeader($Path, "macos")) {
19602 return 1;
19603 }
19604 }
19605 }
19606
19607 # valid
19608 return 0;
19609}
19610
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019611sub skipHeader($$)
19612{
19613 my ($Path, $LibVersion) = @_;
19614 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019615 if(defined $Cache{"skipHeader"}{$Path}) {
19616 return $Cache{"skipHeader"}{$Path};
19617 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019618 if(defined $Tolerance and $Tolerance=~/1|2/)
19619 { # --tolerant
19620 if(skipAlienHeader($Path)) {
19621 return ($Cache{"skipHeader"}{$Path} = 1);
19622 }
19623 }
19624 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19625 return 0;
19626 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019627 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19628}
19629
19630sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631{ # returns:
19632 # 1 - if header should NOT be included and checked
19633 # 2 - if header should NOT be included, but should be checked
19634 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019635 my $Name = get_filename($Path);
19636 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019637 return $Kind;
19638 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019639 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19640 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019641 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019642 if(index($Path, $D)!=-1)
19643 {
19644 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19645 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019647 }
19648 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019649 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19650 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019651 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019652 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19653 {
19654 if($Name=~/$P/) {
19655 return $Kind;
19656 }
19657 if($P=~/[\/\\]/ and $Path=~/$P/) {
19658 return $Kind;
19659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019660 }
19661 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019662
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019663 return 0;
19664}
19665
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019666sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019667{
19668 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019669 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019670 { # system directory
19671 return;
19672 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019673 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019674 { # already registered
19675 return;
19676 }
19677 foreach my $Path (find_libs($Dir,"",1))
19678 {
19679 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019680 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019681 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019682 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019683 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19684}
19685
19686sub registerObject($$)
19687{
19688 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019689
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019690 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019691 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019692 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019693 {
19694 if(my $SONAME = getSONAME($Path)) {
19695 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19696 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019697 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019698 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19699 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019700 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019701
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019702 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019703 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019704 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019705 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019706 if($ObjArch ne getArch_GCC($LibVersion))
19707 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19708 $CheckedArch{$LibVersion} = 1;
19709 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 +040019710 }
19711 }
19712 }
19713}
19714
19715sub getArch_Object($)
19716{
19717 my $Path = $_[0];
19718
19719 my %MachineType = (
19720 "14C" => "x86",
19721 "8664" => "x86_64",
19722 "1C0" => "arm",
19723 "200" => "ia64"
19724 );
19725
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019726 my %ArchName = (
19727 "s390:31-bit" => "s390",
19728 "s390:64-bit" => "s390x",
19729 "powerpc:common" => "ppc32",
19730 "powerpc:common64" => "ppc64",
19731 "i386:x86-64" => "x86_64",
19732 "mips:3000" => "mips",
19733 "sparc:v8plus" => "sparcv9"
19734 );
19735
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019736 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019737 {
19738 my $DumpbinCmd = get_CmdPath("dumpbin");
19739 if(not $DumpbinCmd) {
19740 exitStatus("Not_Found", "can't find \"dumpbin\"");
19741 }
19742
19743 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19744 my $Out = `$Cmd`;
19745
19746 if($Out=~/(\w+)\smachine/)
19747 {
19748 if(my $Type = $MachineType{uc($1)})
19749 {
19750 return $Type;
19751 }
19752 }
19753 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019754 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019755 {
19756 my $ObjdumpCmd = get_CmdPath("objdump");
19757 if(not $ObjdumpCmd) {
19758 exitStatus("Not_Found", "can't find \"objdump\"");
19759 }
19760
19761 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019762
19763 if($OSgroup eq "windows") {
19764 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19765 }
19766 else {
19767 $Cmd = "LANG=$LOCALE ".$Cmd;
19768 }
19769 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019770
19771 if($Out=~/architecture:\s+([\w\-\:]+)/)
19772 {
19773 my $Arch = $1;
19774 if($Arch=~s/\:(.+)//)
19775 {
19776 my $Suffix = $1;
19777
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019778 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019779 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019780 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019781 }
19782 }
19783
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019784 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019785 $Arch = "x86";
19786 }
19787
19788 if($Arch eq "x86-64") {
19789 $Arch = "x86_64";
19790 }
19791
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019792 if($Arch eq "ia64-elf64") {
19793 $Arch = "ia64";
19794 }
19795
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019796 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019797 }
19798 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019799 elsif($OStarget=~/macos/)
19800 {
19801 my $OtoolCmd = get_CmdPath("otool");
19802 if(not $OtoolCmd) {
19803 exitStatus("Not_Found", "can't find \"otool\"");
19804 }
19805
19806 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19807 my $Out = qx/$Cmd/;
19808
19809 if($Out=~/X86_64/i) {
19810 return "x86_64";
19811 }
19812 elsif($Out=~/X86/i) {
19813 return "x86";
19814 }
19815 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019816 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019817 {
19818 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019819 # TODO
19820 }
19821
19822 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019823}
19824
19825sub getSONAME($)
19826{
19827 my $Path = $_[0];
19828 return if(not $Path);
19829 if(defined $Cache{"getSONAME"}{$Path}) {
19830 return $Cache{"getSONAME"}{$Path};
19831 }
19832 my $ObjdumpCmd = get_CmdPath("objdump");
19833 if(not $ObjdumpCmd) {
19834 exitStatus("Not_Found", "can't find \"objdump\"");
19835 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019836 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019837 if($OSgroup eq "windows") {
19838 $SonameCmd .= " | find \"SONAME\"";
19839 }
19840 else {
19841 $SonameCmd .= " | grep SONAME";
19842 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019843 if(my $SonameInfo = `$SonameCmd`)
19844 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019845 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19846 return ($Cache{"getSONAME"}{$Path} = $1);
19847 }
19848 }
19849 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019850}
19851
19852sub getSOPaths_Dest($$)
19853{
19854 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019855 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019856 return ();
19857 }
19858 if(-f $Dest)
19859 {
19860 if(not parse_libname($Dest, "name", $OStarget)) {
19861 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19862 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019863 registerObject($Dest, $LibVersion);
19864 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019865 return ($Dest);
19866 }
19867 elsif(-d $Dest)
19868 {
19869 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019870 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019871 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019872 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19873 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019874 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019875 { # all files and symlinks that match the name of a library
19876 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19877 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019878 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019879 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019880 }
19881 }
19882 }
19883 else
19884 { # search for all files and symlinks
19885 foreach my $Path (find_libs($Dest,"",""))
19886 {
19887 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019888 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019889 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019890 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019891 }
19892 if($OSgroup eq "macos")
19893 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019894 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019895 {
19896 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019897 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019898 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019899 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19900 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019901 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019902 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019903 }
19904 }
19905 }
19906 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019907 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019908 }
19909 else {
19910 return ();
19911 }
19912}
19913
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019914sub isCyclical($$)
19915{
19916 my ($Stack, $Value) = @_;
19917 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019918}
19919
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019920sub getGCC_Opts($)
19921{ # to use in module
19922 my $LibVersion = $_[0];
19923
19924 my @Opts = ();
19925
19926 if($CompilerOptions{$LibVersion})
19927 { # user-defined options
19928 push(@Opts, $CompilerOptions{$LibVersion});
19929 }
19930 if($GccOptions)
19931 { # additional
19932 push(@Opts, $GccOptions);
19933 }
19934
19935 if(@Opts) {
19936 return join(" ", @Opts);
19937 }
19938
19939 return undef;
19940}
19941
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019942sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019943{
19944 my $LibVersion = $_[0];
19945
19946 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19947 return $Cache{"getArch_GCC"}{$LibVersion};
19948 }
19949
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019950 if(not $GCC_PATH) {
19951 return undef;
19952 }
19953
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019954 my $Arch = undef;
19955
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019956 if(my $Target = get_dumpmachine($GCC_PATH))
19957 {
19958 if($Target=~/x86_64/) {
19959 $Arch = "x86_64";
19960 }
19961 elsif($Target=~/i[3-6]86/) {
19962 $Arch = "x86";
19963 }
19964 elsif($Target=~/\Aarm/i) {
19965 $Arch = "arm";
19966 }
19967 }
19968
19969 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019970 {
19971 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19972
19973 my $Cmd = $GCC_PATH." test.c -o test";
19974 if(my $Opts = getGCC_Opts($LibVersion))
19975 { # user-defined options
19976 $Cmd .= " ".$Opts;
19977 }
19978
19979 chdir($TMP_DIR);
19980 system($Cmd);
19981 chdir($ORIG_DIR);
19982
19983 $Arch = getArch_Object("$TMP_DIR/test");
19984
19985 unlink("$TMP_DIR/test.c");
19986 unlink("$TMP_DIR/test");
19987 }
19988
19989 if(not $Arch) {
19990 exitStatus("Error", "can't check ARCH type");
19991 }
19992
19993 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19994}
19995
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019996sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019997{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019998 my $LibVersion = $_[0];
19999
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020000 my $Size = undef;
20001
20002 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020003 if(my $Arch = getArch($LibVersion))
20004 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020005 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020006 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020007 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020008 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20009 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020010 }
20011 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020012
20013 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020014 {
20015 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020016
20017 my $Cmd = $GCC_PATH." -E -dD empty.h";
20018 if(my $Opts = getGCC_Opts($LibVersion))
20019 { # user-defined options
20020 $Cmd .= " ".$Opts;
20021 }
20022
20023 chdir($TMP_DIR);
20024 my $Defines = `$Cmd`;
20025 chdir($ORIG_DIR);
20026
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020027 unlink("$TMP_DIR/empty.h");
20028
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020029 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20030 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020031 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020032 }
20033 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20034 { # GCC 3
20035 my $PTRDIFF = $1;
20036 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020037 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020038 }
20039 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020040 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020041 }
20042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020043 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020044
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020045 if(not $Size) {
20046 exitStatus("Error", "can't check WORD size");
20047 }
20048
20049 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020050}
20051
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020052sub getWordSize($)
20053{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020054 return $WORD_SIZE{$_[0]};
20055}
20056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020057sub majorVersion($)
20058{
20059 my $V = $_[0];
20060 return 0 if(not $V);
20061 my @VParts = split(/\./, $V);
20062 return $VParts[0];
20063}
20064
20065sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020066{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020067 my ($V1, $V2) = @_;
20068 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020069 my @V1Parts = split(/\./, $V1);
20070 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020071 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20072 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020073 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20074 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20075 }
20076 return -1 if($#V1Parts < $#V2Parts);
20077 return 1 if($#V1Parts > $#V2Parts);
20078 return 0;
20079}
20080
20081sub read_ABI_Dump($$)
20082{
20083 my ($LibVersion, $Path) = @_;
20084 return if(not $LibVersion or not -e $Path);
20085 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020086 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020087 { # input *.abi
20088 $FilePath = $Path;
20089 }
20090 else
20091 { # input *.abi.tar.gz
20092 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020093 if(not isDump_U($FilePath)) {
20094 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020096 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020097
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020098 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020099
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020100 my $Line = readLineNum($FilePath, 0);
20101 if($Line=~/xml/)
20102 { # XML format
20103 loadModule("XmlDump");
20104 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020105 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020106 else
20107 { # Perl Data::Dumper format (default)
20108 open(DUMP, $FilePath);
20109 local $/ = undef;
20110 my $Content = <DUMP>;
20111 close(DUMP);
20112
20113 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20114 { # remove temp file
20115 unlink($FilePath);
20116 }
20117 if($Content!~/};\s*\Z/) {
20118 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20119 }
20120 $ABI = eval($Content);
20121 if(not $ABI) {
20122 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020124 }
20125 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020126 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020127 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020128 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020129 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020130 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020131 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020132 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020133 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020134
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020135 if($ABI->{"PublicABI"}) {
20136 $UsedDump{$LibVersion}{"Public"} = 1;
20137 }
20138
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020139 if($ABI->{"ABI_DUMP_VERSION"})
20140 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020141 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020142 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020143 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020144 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020145 }
20146 else
20147 { # support for old ABI dumps
20148 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020149 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020150 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020151 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020152 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020153
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020154 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020155 {
20156 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 +040020157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020158
20159 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20160 { # DWARF ABI Dump
20161 $UseConv_Real{$LibVersion}{"P"} = 1;
20162 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20163
20164 $UsedDump{$LibVersion}{"DWARF"} = 1;
20165
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020166 if(not $TargetComponent_Opt)
20167 {
20168 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20169 $TargetComponent = "module";
20170 }
20171 else {
20172 $TargetComponent = "object";
20173 }
20174 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020175 }
20176
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020177 if(not checkDump($LibVersion, "2.11"))
20178 { # old ABI dumps
20179 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020180 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020181 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020182 { # ABI dump created with --binary option
20183 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20184 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020185 else
20186 { # default
20187 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20188 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020189
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020190 if(defined $ABI->{"Mode"}
20191 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020192 { # --ext option
20193 $ExtendedCheck = 1;
20194 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020195 if($ABI->{"Extra"}) {
20196 $ExtraDump = 1;
20197 }
20198
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020199 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020200 {
20201 $UsedDump{$LibVersion}{"L"} = $Lang;
20202 setLanguage($LibVersion, $Lang);
20203 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020204 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020205 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020206 }
20207 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020208 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020209 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020210 if(not $TInfo)
20211 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020212 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020213 }
20214 my %Tid_TDid = ();
20215 foreach my $TDid (keys(%{$TInfo}))
20216 {
20217 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20218 {
20219 $MAX_ID = $Tid if($Tid>$MAX_ID);
20220 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020221 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020222 }
20223 }
20224 my %NewID = ();
20225 foreach my $Tid (keys(%Tid_TDid))
20226 {
20227 my @TDids = keys(%{$Tid_TDid{$Tid}});
20228 if($#TDids>=1)
20229 {
20230 foreach my $TDid (@TDids)
20231 {
20232 if($TDid) {
20233 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20234 }
20235 else
20236 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020237 my $ID = ++$MAX_ID;
20238
20239 $NewID{$TDid}{$Tid} = $ID;
20240 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20241 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020242 }
20243 }
20244 }
20245 else
20246 {
20247 my $TDid = $TDids[0];
20248 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20249 }
20250 }
20251 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20252 {
20253 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20254 if(defined $Info{"BaseType"})
20255 {
20256 my $Bid = $Info{"BaseType"}{"Tid"};
20257 my $BDid = $Info{"BaseType"}{"TDid"};
20258 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020259 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020260 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20261 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020263 }
20264 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020266 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020267 read_Machine_DumpInfo($ABI, $LibVersion);
20268 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020269 if(not $SymbolInfo{$LibVersion})
20270 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020271 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020272 }
20273 if(not keys(%{$SymbolInfo{$LibVersion}}))
20274 { # validation of old-version dumps
20275 if(not $ExtendedCheck) {
20276 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20277 }
20278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020279 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020280 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020282 else
20283 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020284 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020285 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020286 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020287 }
20288 if(not $DepSymbols)
20289 { # Cannot reconstruct DepSymbols. This may result in false
20290 # positives if the old dump is for library 2. Not a problem if
20291 # old dumps are only from old libraries.
20292 $DepSymbols = {};
20293 }
20294 foreach my $Symbol (keys(%{$DepSymbols})) {
20295 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020297 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020298 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020299
20300 if(my $V = $TargetVersion{$LibVersion}) {
20301 $Descriptor{$LibVersion}{"Version"} = $V;
20302 }
20303 else {
20304 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20305 }
20306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020307 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020308 { # if not defined by -skip-types option
20309 if(defined $ABI->{"SkipTypes"})
20310 {
20311 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20312 {
20313 $SkipTypes{$LibVersion}{$TName} = 1;
20314 }
20315 }
20316 if(defined $ABI->{"OpaqueTypes"})
20317 { # support for old dumps
20318 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20319 {
20320 $SkipTypes{$LibVersion}{$TName} = 1;
20321 }
20322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020323 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020324
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020325 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020326 { # if not defined by -skip-symbols option
20327 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20328 if(not $SkipSymbols{$LibVersion})
20329 { # support for old dumps
20330 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20331 }
20332 if(not $SkipSymbols{$LibVersion})
20333 { # support for old dumps
20334 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020336 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020337 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020338
20339 if(not $TargetHeaders{$LibVersion})
20340 { # if not defined by -headers-list option
20341 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20342 }
20343
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020344 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020345 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020346 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020347
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020348 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020349 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020350 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020351
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020352 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020353 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020354
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020355 if(not checkDump($LibVersion, "2.10.1")
20356 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020357 { # support for old ABI dumps: added target headers
20358 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020359 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020360 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020361
20362 if(not $ABI->{"PublicABI"})
20363 {
20364 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20365 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20366 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020369 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020370 if(defined $ABI->{"GccConstants"})
20371 { # 3.0
20372 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20373 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20374 }
20375 }
20376
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020377 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020378 if(not $NestedNameSpaces{$LibVersion})
20379 { # support for old dumps
20380 # Cannot reconstruct NameSpaces. This may affect design
20381 # of the compatibility report.
20382 $NestedNameSpaces{$LibVersion} = {};
20383 }
20384 # target system type
20385 # needed to adopt HTML report
20386 if(not $DumpSystem)
20387 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020388 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020389 }
20390 # recreate environment
20391 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20392 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020393 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020394 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020395 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20396 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020397 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020398 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020399 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020400 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20401 {
20402 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20403 setLanguage($LibVersion, "C++");
20404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020405 }
20406 }
20407 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020408 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20409 {
20410 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20411 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20412 }
20413 }
20414
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020415 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020416 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020417 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020418 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020419 {
20420 if(not $Symbol_Library{$LibVersion}{$MnglName}
20421 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20422 push(@VFunc, $MnglName);
20423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020424 }
20425 }
20426 translateSymbols(@VFunc, $LibVersion);
20427 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020428 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20429
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020430 if(not checkDump($LibVersion, "3.0"))
20431 { # support for old ABI dumps
20432 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20433 {
20434 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20435 {
20436 if(ref($BaseType) eq "HASH") {
20437 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20438 }
20439 }
20440 }
20441 }
20442
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020443 if(not checkDump($LibVersion, "3.2"))
20444 { # support for old ABI dumps
20445 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20446 {
20447 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20448 {
20449 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20450 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20451 }
20452 }
20453 }
20454
20455 # repair target headers list
20456 delete($TargetHeaders{$LibVersion});
20457 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020458 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20459 }
20460 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20461 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020462 }
20463
20464 # non-target constants from anon enums
20465 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20466 {
20467 if(not $ExtraDump
20468 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20469 {
20470 delete($Constants{$LibVersion}{$Name});
20471 }
20472 }
20473 }
20474
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020475 if(not checkDump($LibVersion, "2.20"))
20476 { # support for old ABI dumps
20477 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20478 {
20479 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20480
20481 if($TType=~/Struct|Union|Enum|Typedef/)
20482 { # repair complex types first
20483 next;
20484 }
20485
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020486 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020487 {
20488 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20489 if($BType=~/Struct|Union|Enum/i)
20490 {
20491 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20492 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20493 }
20494 }
20495 }
20496 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20497 {
20498 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20499 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20500 if($TType=~/Struct|Union|Enum/) {
20501 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20502 }
20503 }
20504 }
20505
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020506 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020507 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020508 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20509 { # support for old ABI dumps < 2.0 (ACC 1.22)
20510 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20511 {
20512 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20513 {
20514 if($Access ne "public") {
20515 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20516 }
20517 }
20518 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20519 }
20520 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20521 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020522 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20523 { # support for old ABI dumps
20524 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20525 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020526 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20527 { # DWARF ABI Dumps
20528 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20529 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020530 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20531 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20532 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020533
20534 # support for old formatting of type names
20535 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20536
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020537 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20538 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020539 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020540 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20541 {
20542 if($SubId eq $TypeId)
20543 { # Fix erroneus ABI dump
20544 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20545 next;
20546 }
20547
20548 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020550 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020551 if($TInfo{"Type"} eq "MethodPtr")
20552 {
20553 if(defined $TInfo{"Param"})
20554 { # support for old ABI dumps <= 1.17
20555 if(not defined $TInfo{"Param"}{"0"})
20556 {
20557 my $Max = keys(%{$TInfo{"Param"}});
20558 foreach my $Pos (1 .. $Max) {
20559 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20560 }
20561 delete($TInfo{"Param"}{$Max});
20562 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20563 }
20564 }
20565 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020566 if($TInfo{"BaseType"} eq $TypeId)
20567 { # fix ABI dump
20568 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20569 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020570
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020571 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020572 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020573 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020574 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020575 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20576 if(not $BName)
20577 { # broken type
20578 next;
20579 }
20580 if($TInfo{"Name"} eq $BName)
20581 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020582 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020583 next;
20584 }
20585 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20586 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020587 }
20588 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020589 }
20590 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20591 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020592 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020593 }
20594 }
20595
20596 if(not checkDump($LibVersion, "2.15"))
20597 { # support for old ABI dumps
20598 my %Dups = ();
20599 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20600 {
20601 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020602 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020603 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20604 { # remove template decls
20605 delete($SymbolInfo{$LibVersion}{$InfoId});
20606 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020608 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020609 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20610 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020611 { # templates
20612 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020613 }
20614 }
20615 }
20616
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020617 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20618 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020619 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20620 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20621 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20622 { # support for old ABI dumps (< 3.1)
20623 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20624 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20625 { # add "this" first parameter
20626 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20627 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20628
20629 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20630 {
20631 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20632 foreach my $Pos (reverse(0 .. $#Pos)) {
20633 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20634 }
20635 }
20636 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20637 }
20638 }
20639
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020640 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20641 { # ABI dumps have no mangled names for C-functions
20642 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20643 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020644 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20645 { # support for old ABI dumps
20646 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20647 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020648 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20649 { # DWARF ABI Dumps
20650 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20651 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020652 }
20653
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020654 $Descriptor{$LibVersion}{"Dump"} = 1;
20655}
20656
20657sub read_Machine_DumpInfo($$)
20658{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020659 my ($ABI, $LibVersion) = @_;
20660 if($ABI->{"Arch"}) {
20661 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020662 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020663 if($ABI->{"WordSize"}) {
20664 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 }
20666 else
20667 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020668 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020669 }
20670 if(not $WORD_SIZE{$LibVersion})
20671 { # support for old dumps (<1.23)
20672 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20673 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020674 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020675 }
20676 else
20677 {
20678 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020679 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020680 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020681 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20682 { # any "pointer"-type
20683 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020684 last;
20685 }
20686 }
20687 if($PSize)
20688 { # a pointer type size
20689 $WORD_SIZE{$LibVersion} = $PSize;
20690 }
20691 else {
20692 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20693 }
20694 }
20695 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020696 if($ABI->{"GccVersion"}) {
20697 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020698 }
20699}
20700
20701sub read_Libs_DumpInfo($$)
20702{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020703 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020704 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20705 if(not $Library_Symbol{$LibVersion})
20706 { # support for old dumps
20707 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020709 if(keys(%{$Library_Symbol{$LibVersion}})
20710 and not $DumpAPI) {
20711 $Descriptor{$LibVersion}{"Libs"} = "OK";
20712 }
20713}
20714
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020715sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020716{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020717 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020718
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020719 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020720 and not $DumpAPI) {
20721 $Descriptor{$LibVersion}{"Headers"} = "OK";
20722 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020723 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020724 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020725 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020726 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020727 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020728
20729 if(keys(%{$ABI->{"Sources"}})
20730 and not $DumpAPI) {
20731 $Descriptor{$LibVersion}{"Sources"} = "OK";
20732 }
20733 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020734 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020735 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20736 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020738}
20739
20740sub find_libs($$$)
20741{
20742 my ($Path, $Type, $MaxDepth) = @_;
20743 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020744 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020745}
20746
20747sub createDescriptor($$)
20748{
20749 my ($LibVersion, $Path) = @_;
20750 if(not $LibVersion or not $Path
20751 or not -e $Path) {
20752 return "";
20753 }
20754 if(-d $Path)
20755 { # directory with headers files and shared objects
20756 return "
20757 <version>
20758 ".$TargetVersion{$LibVersion}."
20759 </version>
20760
20761 <headers>
20762 $Path
20763 </headers>
20764
20765 <libs>
20766 $Path
20767 </libs>";
20768 }
20769 else
20770 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020771 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772 { # standard XML-descriptor
20773 return readFile($Path);
20774 }
20775 elsif(is_header($Path, 2, $LibVersion))
20776 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020777 $CheckHeadersOnly = 1;
20778
20779 if($LibVersion==1) {
20780 $TargetVersion{$LibVersion} = "X";
20781 }
20782
20783 if($LibVersion==2) {
20784 $TargetVersion{$LibVersion} = "Y";
20785 }
20786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787 return "
20788 <version>
20789 ".$TargetVersion{$LibVersion}."
20790 </version>
20791
20792 <headers>
20793 $Path
20794 </headers>
20795
20796 <libs>
20797 none
20798 </libs>";
20799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020800 else
20801 { # standard XML-descriptor
20802 return readFile($Path);
20803 }
20804 }
20805}
20806
20807sub detect_lib_default_paths()
20808{
20809 my %LPaths = ();
20810 if($OSgroup eq "bsd")
20811 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020812 if(my $LdConfig = get_CmdPath("ldconfig"))
20813 {
20814 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20815 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020816 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20817 {
20818 my $Name = "lib".$1;
20819 if(not defined $LPaths{$Name}) {
20820 $LPaths{$Name} = $2;
20821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020822 }
20823 }
20824 }
20825 else {
20826 printMsg("WARNING", "can't find ldconfig");
20827 }
20828 }
20829 else
20830 {
20831 if(my $LdConfig = get_CmdPath("ldconfig"))
20832 {
20833 if($SystemRoot and $OSgroup eq "linux")
20834 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20835 if(-e $SystemRoot."/etc/ld.so.conf") {
20836 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20837 }
20838 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020839 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20840 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020841 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20842 {
20843 my ($Name, $Path) = ($1, $2);
20844 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020845 if(not defined $LPaths{$Name})
20846 { # get first element from the list of available paths
20847
20848 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20849 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20850 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20851
20852 $LPaths{$Name} = $Path;
20853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020854 }
20855 }
20856 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020857 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020858 printMsg("WARNING", "can't find ldconfig");
20859 }
20860 }
20861 return \%LPaths;
20862}
20863
20864sub detect_bin_default_paths()
20865{
20866 my $EnvPaths = $ENV{"PATH"};
20867 if($OSgroup eq "beos") {
20868 $EnvPaths.=":".$ENV{"BETOOLS"};
20869 }
20870 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020871 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020872 {
20873 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020874 next if(not $Path);
20875 if($SystemRoot
20876 and $Path=~/\A\Q$SystemRoot\E\//)
20877 { # do NOT use binaries from target system
20878 next;
20879 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020880 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020881 }
20882}
20883
20884sub detect_inc_default_paths()
20885{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020886 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020887 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020888 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020889 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020890 next if(index($Line, "/cc1plus ")!=-1);
20891
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020892 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20893 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020894 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020895 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020896 if(index($Path, "c++")!=-1
20897 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020898 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020899 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020900 if(not defined $MAIN_CPP_DIR
20901 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20902 $MAIN_CPP_DIR = $Path;
20903 }
20904 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020905 elsif(index($Path, "gcc")!=-1) {
20906 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020907 }
20908 else
20909 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020910 if($Path=~/local[\/\\]+include/)
20911 { # local paths
20912 next;
20913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020914 if($SystemRoot
20915 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20916 { # The GCC include path for user headers is not a part of the system root
20917 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20918 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20919 next;
20920 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020921 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020922 }
20923 }
20924 }
20925 unlink("$TMP_DIR/empty.h");
20926 return %DPaths;
20927}
20928
20929sub detect_default_paths($)
20930{
20931 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20932 my $Search = $_[0];
20933 if($Search!~/inc/) {
20934 $HSearch = 0;
20935 }
20936 if($Search!~/lib/) {
20937 $LSearch = 0;
20938 }
20939 if($Search!~/bin/) {
20940 $BSearch = 0;
20941 }
20942 if($Search!~/gcc/) {
20943 $GSearch = 0;
20944 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020945 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020946 { # <search_headers> section of the XML descriptor
20947 # do NOT search for systems headers
20948 $HSearch = 0;
20949 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020950 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020951 { # <search_libs> section of the XML descriptor
20952 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953 $LSearch = 0;
20954 }
20955 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20956 { # additional search paths
20957 next if($Type eq "include" and not $HSearch);
20958 next if($Type eq "lib" and not $LSearch);
20959 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020960 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020961 }
20962 if($OSgroup ne "windows")
20963 { # unix-like
20964 foreach my $Type ("include", "lib", "bin")
20965 { # automatic detection of system "devel" directories
20966 next if($Type eq "include" and not $HSearch);
20967 next if($Type eq "lib" and not $LSearch);
20968 next if($Type eq "bin" and not $BSearch);
20969 my ($UsrDir, $RootDir) = ("/usr", "/");
20970 if($SystemRoot and $Type ne "bin")
20971 { # 1. search for target headers and libraries
20972 # 2. use host commands: ldconfig, readelf, etc.
20973 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20974 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020975 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020976 if(-d $RootDir."/".$Type)
20977 { # if "/lib" is symbolic link
20978 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020979 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020980 }
20981 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020982 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020983 }
20984 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020985 if(-d $UsrDir)
20986 {
20987 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020988 if(-d $UsrDir."/".$Type)
20989 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020990 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020991 }
20992 }
20993 }
20994 }
20995 if($BSearch)
20996 {
20997 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020998 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020999 }
21000 # check environment variables
21001 if($OSgroup eq "beos")
21002 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021003 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021004 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021005 if($_ eq ".") {
21006 next;
21007 }
21008 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21009 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21010 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021011 }
21012 }
21013 if($HSearch)
21014 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021015 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21016 split(/:|;/, $ENV{"BEINCLUDES"})
21017 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021018 }
21019 if($LSearch)
21020 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021021 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21022 split(/:|;/, $ENV{"BELIBRARIES"}),
21023 split(/:|;/, $ENV{"LIBRARY_PATH"})
21024 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021025 }
21026 }
21027 if($LSearch)
21028 { # using linker to get system paths
21029 if(my $LPaths = detect_lib_default_paths())
21030 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021031 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021032 foreach my $Name (keys(%{$LPaths}))
21033 {
21034 if($SystemRoot
21035 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21036 { # wrong ldconfig configuration
21037 # check your <sysroot>/etc/ld.so.conf
21038 next;
21039 }
21040 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 if(my $Dir = get_dirname($LPaths->{$Name})) {
21042 $Dirs{$Dir} = 1;
21043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021044 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021045 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021046 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021047 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021048 }
21049 if($BSearch)
21050 {
21051 if($CrossGcc)
21052 { # --cross-gcc=arm-linux-gcc
21053 if(-e $CrossGcc)
21054 { # absolute or relative path
21055 $GCC_PATH = get_abs_path($CrossGcc);
21056 }
21057 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21058 { # command name
21059 $GCC_PATH = $CrossGcc;
21060 }
21061 else {
21062 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21063 }
21064 if($GCC_PATH=~/\s/) {
21065 $GCC_PATH = "\"".$GCC_PATH."\"";
21066 }
21067 }
21068 }
21069 if($GSearch)
21070 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021071 if(not $CrossGcc)
21072 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021073 $GCC_PATH = get_CmdPath("gcc");
21074 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021075 if(not $GCC_PATH)
21076 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021077 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021078 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021079 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021080 { # select the latest version
21081 @GCCs = sort {$b cmp $a} @GCCs;
21082 if(check_gcc($GCCs[0], "3"))
21083 {
21084 $GCC_PATH = $GCCs[0];
21085 last;
21086 }
21087 }
21088 }
21089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021090 if(not $GCC_PATH) {
21091 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21092 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021093
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021094 my $GCC_Ver = get_dumpversion($GCC_PATH);
21095 if($GCC_Ver eq "4.8")
21096 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21097 my $Info = `$GCC_PATH --version`;
21098
21099 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21100 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21101 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21102 $GCC_Ver = $2;
21103 }
21104 }
21105
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021106 if($OStarget=~/macos/)
21107 {
21108 my $Info = `$GCC_PATH --version`;
21109
21110 if($Info=~/clang/i) {
21111 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21112 }
21113 }
21114
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021115 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021116 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021117 my $GccTarget = get_dumpmachine($GCC_PATH);
21118
21119 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021120 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021121 $OStarget = "linux";
21122 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021123 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021124 elsif($GccTarget=~/symbian/)
21125 {
21126 $OStarget = "symbian";
21127 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21128 }
21129
21130 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21131
21132 # check GCC version
21133 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21134 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021135 # introduced in 4.8 and fixed in 4.8.3
21136 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.");
21137
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021138 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021139 }
21140 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021141 else {
21142 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143 }
21144 }
21145 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021146 {
21147 # GCC standard paths
21148 if($GCC_PATH and not $NoStdInc)
21149 {
21150 my %DPaths = detect_inc_default_paths();
21151 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21152 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21153 @DefaultIncPaths = @{$DPaths{"Inc"}};
21154 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21155 }
21156
21157 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021158 my $IncPath = "/usr/include";
21159 if($SystemRoot) {
21160 $IncPath = $SystemRoot.$IncPath;
21161 }
21162 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021163 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021164 }
21165 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021166
21167 if($ExtraInfo)
21168 {
21169 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21170 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021172}
21173
21174sub getLIB_EXT($)
21175{
21176 my $Target = $_[0];
21177 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21178 return $Ext;
21179 }
21180 return $OS_LibExt{$LIB_TYPE}{"default"};
21181}
21182
21183sub getAR_EXT($)
21184{
21185 my $Target = $_[0];
21186 if(my $Ext = $OS_Archive{$Target}) {
21187 return $Ext;
21188 }
21189 return $OS_Archive{"default"};
21190}
21191
21192sub get_dumpversion($)
21193{
21194 my $Cmd = $_[0];
21195 return "" if(not $Cmd);
21196 if($Cache{"get_dumpversion"}{$Cmd}) {
21197 return $Cache{"get_dumpversion"}{$Cmd};
21198 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021199 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021200 chomp($V);
21201 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21202}
21203
21204sub get_dumpmachine($)
21205{
21206 my $Cmd = $_[0];
21207 return "" if(not $Cmd);
21208 if($Cache{"get_dumpmachine"}{$Cmd}) {
21209 return $Cache{"get_dumpmachine"}{$Cmd};
21210 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021211 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021212 chomp($Machine);
21213 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21214}
21215
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021216sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217{
21218 my $Cmd = $_[0];
21219 return "" if(not $Cmd);
21220 my @Options = (
21221 "--version",
21222 "-help"
21223 );
21224 foreach my $Opt (@Options)
21225 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021226 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021227 if($Info) {
21228 return 1;
21229 }
21230 }
21231 return 0;
21232}
21233
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021234sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021235{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021236 my ($Cmd, $ReqVer) = @_;
21237 return 0 if(not $Cmd or not $ReqVer);
21238 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21239 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021240 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021241 if(my $GccVer = get_dumpversion($Cmd))
21242 {
21243 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21244 if(cmpVersions($GccVer, $ReqVer)>=0) {
21245 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21246 }
21247 }
21248 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021249}
21250
21251sub get_depth($)
21252{
21253 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021254 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021255 }
21256 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21257}
21258
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021259sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021260{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021261 return if($Cache{"registerGccHeaders"}); # this function should be called once
21262
21263 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021264 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021265 my @Headers = cmd_find($Path,"f");
21266 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21267 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021268 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021269 my $FileName = get_filename($HPath);
21270 if(not defined $DefaultGccHeader{$FileName})
21271 { # skip duplicated
21272 $DefaultGccHeader{$FileName} = $HPath;
21273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021274 }
21275 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021276 $Cache{"registerGccHeaders"} = 1;
21277}
21278
21279sub registerCppHeaders()
21280{
21281 return if($Cache{"registerCppHeaders"}); # this function should be called once
21282
21283 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021284 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021285 my @Headers = cmd_find($CppDir,"f");
21286 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21287 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021288 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021289 my $FileName = get_filename($Path);
21290 if(not defined $DefaultCppHeader{$FileName})
21291 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021292 $DefaultCppHeader{$FileName} = $Path;
21293 }
21294 }
21295 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021296 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021297}
21298
21299sub parse_libname($$$)
21300{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021301 return "" if(not $_[0]);
21302 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21303 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021304 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021305 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21306}
21307
21308sub parse_libname_I($$$)
21309{
21310 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021312 if($Target eq "symbian") {
21313 return parse_libname_symbian($Name, $Type);
21314 }
21315 elsif($Target eq "windows") {
21316 return parse_libname_windows($Name, $Type);
21317 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021318
21319 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021320 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021321 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021322 { # libSDL-1.2.so.0.7.1
21323 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021324 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021325 if($Type eq "name")
21326 { # libSDL-1.2
21327 # libwbxml2
21328 return $2;
21329 }
21330 elsif($Type eq "name+ext")
21331 { # libSDL-1.2.so
21332 # libwbxml2.so
21333 return $1;
21334 }
21335 elsif($Type eq "version")
21336 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021337 if(defined $7
21338 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021339 { # 0.7.1
21340 return $7;
21341 }
21342 else
21343 { # libc-2.5.so (=>2.5 version)
21344 my $MV = $5;
21345 $MV=~s/\A[\-\_]+//g;
21346 return $MV;
21347 }
21348 }
21349 elsif($Type eq "short")
21350 { # libSDL
21351 # libwbxml2
21352 return $3;
21353 }
21354 elsif($Type eq "shortest")
21355 { # SDL
21356 # wbxml
21357 return shortest_name($3);
21358 }
21359 }
21360 return "";# error
21361}
21362
21363sub parse_libname_symbian($$)
21364{
21365 my ($Name, $Type) = @_;
21366 my $Ext = getLIB_EXT("symbian");
21367 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21368 { # libpthread{00010001}.dso
21369 if($Type eq "name")
21370 { # libpthread{00010001}
21371 return $2;
21372 }
21373 elsif($Type eq "name+ext")
21374 { # libpthread{00010001}.dso
21375 return $1;
21376 }
21377 elsif($Type eq "version")
21378 { # 00010001
21379 my $V = $4;
21380 $V=~s/\{(.+)\}/$1/;
21381 return $V;
21382 }
21383 elsif($Type eq "short")
21384 { # libpthread
21385 return $3;
21386 }
21387 elsif($Type eq "shortest")
21388 { # pthread
21389 return shortest_name($3);
21390 }
21391 }
21392 return "";# error
21393}
21394
21395sub parse_libname_windows($$)
21396{
21397 my ($Name, $Type) = @_;
21398 my $Ext = getLIB_EXT("windows");
21399 if($Name=~/((.+?)\.$Ext)\Z/)
21400 { # netapi32.dll
21401 if($Type eq "name")
21402 { # netapi32
21403 return $2;
21404 }
21405 elsif($Type eq "name+ext")
21406 { # netapi32.dll
21407 return $1;
21408 }
21409 elsif($Type eq "version")
21410 { # DLL version embedded
21411 # at binary-level
21412 return "";
21413 }
21414 elsif($Type eq "short")
21415 { # netapi32
21416 return $2;
21417 }
21418 elsif($Type eq "shortest")
21419 { # netapi
21420 return shortest_name($2);
21421 }
21422 }
21423 return "";# error
21424}
21425
21426sub shortest_name($)
21427{
21428 my $Name = $_[0];
21429 # remove prefix
21430 $Name=~s/\A(lib|open)//;
21431 # remove suffix
21432 $Name=~s/[\W\d_]+\Z//i;
21433 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21434 return $Name;
21435}
21436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021437sub createSymbolsList($$$$$)
21438{
21439 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021440
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021441 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021442 prepareSymbols(1);
21443
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021444 my %SymbolHeaderLib = ();
21445 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021447 # Get List
21448 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21449 {
21450 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021451 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021452 next;
21453 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021454 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021455 { # skip other symbols
21456 next;
21457 }
21458 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21459 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021460 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021461 next;
21462 }
21463 my $DyLib = $Symbol_Library{1}{$Symbol};
21464 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021465 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021466 next;
21467 }
21468 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21469 $Total+=1;
21470 }
21471 # Draw List
21472 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21473 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21474 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21475 {
21476 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21477 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021478 my %NS_Symbol = ();
21479 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021480 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021481 }
21482 foreach my $NameSpace (sort keys(%NS_Symbol))
21483 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021484 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021485 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21486 foreach my $Symbol (@SortedInterfaces)
21487 {
21488 my $SubReport = "";
21489 my $Signature = get_Signature($Symbol, 1);
21490 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021491 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021492 }
21493 if($Symbol=~/\A(_Z|\?)/)
21494 {
21495 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021496 $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 +040021497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021498 else {
21499 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21500 }
21501 }
21502 else
21503 {
21504 if($Signature) {
21505 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21506 }
21507 else {
21508 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21509 }
21510 }
21511 $SYMBOLS_LIST .= $SubReport;
21512 }
21513 }
21514 $SYMBOLS_LIST .= "<br/>\n";
21515 }
21516 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021517 # clear info
21518 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21519 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21520 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21521 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021522 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021523 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021524 my $CssStyles = readModule("Styles", "SymbolsList.css");
21525 my $JScripts = readModule("Scripts", "Sections.js");
21526 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021527 my $Title = "$LName: public symbols";
21528 my $Keywords = "$LName, API, symbols";
21529 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021530 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021531 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021532 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021533 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021534 writeFile($SaveTo, $SYMBOLS_LIST);
21535}
21536
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021537sub add_target_libs($)
21538{
21539 foreach (@{$_[0]}) {
21540 $TargetLibs{$_} = 1;
21541 }
21542}
21543
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021544sub is_target_lib($)
21545{
21546 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021547 if(not $LName) {
21548 return 0;
21549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021550 if($TargetLibraryName
21551 and $LName!~/\Q$TargetLibraryName\E/) {
21552 return 0;
21553 }
21554 if(keys(%TargetLibs)
21555 and not $TargetLibs{$LName}
21556 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21557 return 0;
21558 }
21559 return 1;
21560}
21561
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021562sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021563{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021564 my ($H, $V) = @_;
21565 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021566 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021567 if($TargetHeaders{$V}{$H}) {
21568 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021569 }
21570 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021571 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021572}
21573
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021574sub readLibs($)
21575{
21576 my $LibVersion = $_[0];
21577 if($OStarget eq "windows")
21578 { # dumpbin.exe will crash
21579 # without VS Environment
21580 check_win32_env();
21581 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021582 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021583 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021584 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021585}
21586
21587sub dump_sorting($)
21588{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021589 my $Hash = $_[0];
21590 return [] if(not $Hash);
21591 my @Keys = keys(%{$Hash});
21592 return [] if($#Keys<0);
21593 if($Keys[0]=~/\A\d+\Z/)
21594 { # numbers
21595 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021596 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021597 else
21598 { # strings
21599 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021600 }
21601}
21602
21603sub printMsg($$)
21604{
21605 my ($Type, $Msg) = @_;
21606 if($Type!~/\AINFO/) {
21607 $Msg = $Type.": ".$Msg;
21608 }
21609 if($Type!~/_C\Z/) {
21610 $Msg .= "\n";
21611 }
21612 if($Quiet)
21613 { # --quiet option
21614 appendFile($COMMON_LOG_PATH, $Msg);
21615 }
21616 else
21617 {
21618 if($Type eq "ERROR") {
21619 print STDERR $Msg;
21620 }
21621 else {
21622 print $Msg;
21623 }
21624 }
21625}
21626
21627sub exitStatus($$)
21628{
21629 my ($Code, $Msg) = @_;
21630 printMsg("ERROR", $Msg);
21631 exit($ERROR_CODE{$Code});
21632}
21633
21634sub exitReport()
21635{ # the tool has run without any errors
21636 printReport();
21637 if($COMPILE_ERRORS)
21638 { # errors in headers may add false positives/negatives
21639 exit($ERROR_CODE{"Compile_Error"});
21640 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021641 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21642 { # --binary
21643 exit($ERROR_CODE{"Incompatible"});
21644 }
21645 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21646 { # --source
21647 exit($ERROR_CODE{"Incompatible"});
21648 }
21649 elsif($RESULT{"Source"}{"Problems"}
21650 or $RESULT{"Binary"}{"Problems"})
21651 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021652 exit($ERROR_CODE{"Incompatible"});
21653 }
21654 else {
21655 exit($ERROR_CODE{"Compatible"});
21656 }
21657}
21658
21659sub readRules($)
21660{
21661 my $Kind = $_[0];
21662 if(not -f $RULES_PATH{$Kind}) {
21663 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21664 }
21665 my $Content = readFile($RULES_PATH{$Kind});
21666 while(my $Rule = parseTag(\$Content, "rule"))
21667 {
21668 my $RId = parseTag(\$Rule, "id");
21669 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21670 foreach my $Prop (@Properties) {
21671 if(my $Value = parseTag(\$Rule, lc($Prop)))
21672 {
21673 $Value=~s/\n[ ]*//;
21674 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21675 }
21676 }
21677 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21678 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21679 }
21680 else {
21681 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21682 }
21683 }
21684}
21685
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021686sub getReportPath($)
21687{
21688 my $Level = $_[0];
21689 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21690 if($Level eq "Binary")
21691 {
21692 if($BinaryReportPath)
21693 { # --bin-report-path
21694 return $BinaryReportPath;
21695 }
21696 elsif($OutputReportPath)
21697 { # --report-path
21698 return $OutputReportPath;
21699 }
21700 else
21701 { # default
21702 return $Dir."/abi_compat_report.$ReportFormat";
21703 }
21704 }
21705 elsif($Level eq "Source")
21706 {
21707 if($SourceReportPath)
21708 { # --src-report-path
21709 return $SourceReportPath;
21710 }
21711 elsif($OutputReportPath)
21712 { # --report-path
21713 return $OutputReportPath;
21714 }
21715 else
21716 { # default
21717 return $Dir."/src_compat_report.$ReportFormat";
21718 }
21719 }
21720 else
21721 {
21722 if($OutputReportPath)
21723 { # --report-path
21724 return $OutputReportPath;
21725 }
21726 else
21727 { # default
21728 return $Dir."/compat_report.$ReportFormat";
21729 }
21730 }
21731}
21732
21733sub printStatMsg($)
21734{
21735 my $Level = $_[0];
21736 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21737}
21738
21739sub listAffected($)
21740{
21741 my $Level = $_[0];
21742 my $List = "";
21743 foreach (keys(%{$TotalAffected{$Level}}))
21744 {
21745 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21746 { # skip "Low"-severity problems
21747 next;
21748 }
21749 $List .= "$_\n";
21750 }
21751 my $Dir = get_dirname(getReportPath($Level));
21752 if($Level eq "Binary") {
21753 writeFile($Dir."/abi_affected.txt", $List);
21754 }
21755 elsif($Level eq "Source") {
21756 writeFile($Dir."/src_affected.txt", $List);
21757 }
21758}
21759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021760sub printReport()
21761{
21762 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021763 createReport();
21764 if($JoinReport or $DoubleReport)
21765 {
21766 if($RESULT{"Binary"}{"Problems"}
21767 or $RESULT{"Source"}{"Problems"}) {
21768 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021769 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021770 else {
21771 printMsg("INFO", "result: COMPATIBLE");
21772 }
21773 printStatMsg("Binary");
21774 printStatMsg("Source");
21775 if($ListAffected)
21776 { # --list-affected
21777 listAffected("Binary");
21778 listAffected("Source");
21779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021781 elsif($BinaryOnly)
21782 {
21783 if($RESULT{"Binary"}{"Problems"}) {
21784 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21785 }
21786 else {
21787 printMsg("INFO", "result: COMPATIBLE");
21788 }
21789 printStatMsg("Binary");
21790 if($ListAffected)
21791 { # --list-affected
21792 listAffected("Binary");
21793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021794 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021795 elsif($SourceOnly)
21796 {
21797 if($RESULT{"Source"}{"Problems"}) {
21798 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21799 }
21800 else {
21801 printMsg("INFO", "result: COMPATIBLE");
21802 }
21803 printStatMsg("Source");
21804 if($ListAffected)
21805 { # --list-affected
21806 listAffected("Source");
21807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021808 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021809 if($StdOut)
21810 {
21811 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021812 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021813 printMsg("INFO", "compatibility report has been generated to stdout");
21814 }
21815 else
21816 { # default
21817 printMsg("INFO", "compatibility reports have been generated to stdout");
21818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021819 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021820 else
21821 {
21822 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021823 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021824 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21825 }
21826 elsif($DoubleReport)
21827 { # default
21828 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21829 }
21830 elsif($BinaryOnly)
21831 { # --binary
21832 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21833 }
21834 elsif($SourceOnly)
21835 { # --source
21836 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021838 }
21839}
21840
21841sub check_win32_env()
21842{
21843 if(not $ENV{"DevEnvDir"}
21844 or not $ENV{"LIB"}) {
21845 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21846 }
21847}
21848
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021849sub diffSets($$)
21850{
21851 my ($S1, $S2) = @_;
21852 my @SK1 = keys(%{$S1});
21853 my @SK2 = keys(%{$S2});
21854 if($#SK1!=$#SK2) {
21855 return 1;
21856 }
21857 foreach my $K1 (@SK1)
21858 {
21859 if(not defined $S2->{$K1}) {
21860 return 1;
21861 }
21862 }
21863 return 0;
21864}
21865
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021866sub defaultDumpPath($$)
21867{
21868 my ($N, $V) = @_;
21869 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21870}
21871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021872sub create_ABI_Dump()
21873{
21874 if(not -e $DumpAPI) {
21875 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21876 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021877
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021878 if(isDump($DumpAPI)) {
21879 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021880 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021881 else {
21882 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021883 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021884
21885 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021886 { # set to default: N
21887 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021888 }
21889
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021890 initLogging(1);
21891 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021892
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021893 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021894 if($OutputDumpPath)
21895 { # user defined path
21896 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021897 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021898 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21899
21900 if(not $Archive and not $StdOut)
21901 { # check archive utilities
21902 if($OSgroup eq "windows")
21903 { # using zip
21904 my $ZipCmd = get_CmdPath("zip");
21905 if(not $ZipCmd) {
21906 exitStatus("Not_Found", "can't find \"zip\"");
21907 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021908 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021909 else
21910 { # using tar and gzip
21911 my $TarCmd = get_CmdPath("tar");
21912 if(not $TarCmd) {
21913 exitStatus("Not_Found", "can't find \"tar\"");
21914 }
21915 my $GzipCmd = get_CmdPath("gzip");
21916 if(not $GzipCmd) {
21917 exitStatus("Not_Found", "can't find \"gzip\"");
21918 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021919 }
21920 }
21921
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021922 if(not $Descriptor{1}{"Dump"})
21923 {
21924 if(not $CheckHeadersOnly) {
21925 readLibs(1);
21926 }
21927 if($CheckHeadersOnly) {
21928 setLanguage(1, "C++");
21929 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021930 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021931 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021932 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021933 if(not $Descriptor{1}{"Dump"})
21934 {
21935 if($Descriptor{1}{"Headers"}) {
21936 readHeaders(1);
21937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021938 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021939 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021940 if(not keys(%{$SymbolInfo{1}}))
21941 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021942 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021943 {
21944 if($CheckHeadersOnly) {
21945 exitStatus("Empty_Set", "the set of public symbols is empty");
21946 }
21947 else {
21948 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21949 }
21950 }
21951 }
21952 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021953 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021954 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21955 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021956 if($ExtraDump)
21957 { # add unmangled names to the ABI dump
21958 my @Names = ();
21959 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21960 {
21961 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21962 push(@Names, $MnglName);
21963 }
21964 }
21965 translateSymbols(@Names, 1);
21966 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21967 {
21968 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21969 {
21970 if(my $Unmangled = $tr_name{$MnglName})
21971 {
21972 if($MnglName ne $Unmangled) {
21973 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21974 }
21975 }
21976 }
21977 }
21978 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021979
21980 my %GccConstants = (); # built-in GCC constants
21981 foreach my $Name (keys(%{$Constants{1}}))
21982 {
21983 if(not defined $Constants{1}{$Name}{"Header"})
21984 {
21985 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21986 delete($Constants{1}{$Name});
21987 }
21988 }
21989
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021990 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021991 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021992 "TypeInfo" => $TypeInfo{1},
21993 "SymbolInfo" => $SymbolInfo{1},
21994 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021995 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021996 "SymbolVersion" => $SymVer{1},
21997 "LibraryVersion" => $Descriptor{1}{"Version"},
21998 "LibraryName" => $TargetLibraryName,
21999 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022000 "SkipTypes" => $SkipTypes{1},
22001 "SkipSymbols" => $SkipSymbols{1},
22002 "SkipNameSpaces" => $SkipNameSpaces{1},
22003 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022004 "Headers" => \%HeadersInfo,
22005 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022006 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022007 "NameSpaces" => $NestedNameSpaces{1},
22008 "Target" => $OStarget,
22009 "Arch" => getArch(1),
22010 "WordSize" => $WORD_SIZE{1},
22011 "GccVersion" => get_dumpversion($GCC_PATH),
22012 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22013 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22014 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022015 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022016 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022017 }
22018 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022019 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022021 if($ExtendedCheck)
22022 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022023 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022025 if($BinaryOnly)
22026 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022027 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022028 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022029 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022030 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022031 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022032 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22033 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022034 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022035
22036 my $ABI_DUMP = "";
22037 if($UseXML)
22038 {
22039 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022040 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022041 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022042 else
22043 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022044 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022046 if($StdOut)
22047 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022048 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022049 printMsg("INFO", "ABI dump has been generated to stdout");
22050 return;
22051 }
22052 else
22053 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022054 my ($DDir, $DName) = separate_path($DumpPath);
22055 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022056 if(not $Archive) {
22057 $DPath = $DumpPath;
22058 }
22059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022060 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022061
22062 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022063 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022064 close(DUMP);
22065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022066 if(not -s $DPath) {
22067 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22068 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022069 if($Archive) {
22070 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022071 }
22072
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022073 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022074 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022075 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022076 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022077 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022078 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022079 # 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 +040022080 }
22081}
22082
22083sub quickEmptyReports()
22084{ # Quick "empty" reports
22085 # 4 times faster than merging equal dumps
22086 # NOTE: the dump contains the "LibraryVersion" attribute
22087 # if you change the version, then your dump will be different
22088 # OVERCOME: use -v1 and v2 options for comparing dumps
22089 # and don't change version in the XML descriptor (and dumps)
22090 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22091 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22092 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022093 my $FilePath1 = $Descriptor{1}{"Path"};
22094 my $FilePath2 = $Descriptor{2}{"Path"};
22095
22096 if(not isDump_U($FilePath1)) {
22097 $FilePath1 = unpackDump($FilePath1);
22098 }
22099
22100 if(not isDump_U($FilePath2)) {
22101 $FilePath2 = unpackDump($FilePath2);
22102 }
22103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022104 if($FilePath1 and $FilePath2)
22105 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022106 my $Line = readLineNum($FilePath1, 0);
22107 if($Line=~/xml/)
22108 { # XML format
22109 # is not supported yet
22110 return;
22111 }
22112
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022113 local $/ = undef;
22114
22115 open(DUMP1, $FilePath1);
22116 my $Content1 = <DUMP1>;
22117 close(DUMP1);
22118
22119 open(DUMP2, $FilePath2);
22120 my $Content2 = <DUMP2>;
22121 close(DUMP2);
22122
22123 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022124 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022125 # clean memory
22126 undef $Content2;
22127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022128 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022129 my $ABIdump = eval($Content1);
22130
22131 # clean memory
22132 undef $Content1;
22133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022134 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022135 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 +040022136 }
22137 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022138 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022139 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22140 }
22141 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022142 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022143 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22144 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022145 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022146 read_Libs_DumpInfo($ABIdump, 1);
22147 read_Machine_DumpInfo($ABIdump, 1);
22148 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022149
22150 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22151 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22152
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022153 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22154 {
22155 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22156 {
22157 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22158 next;
22159 }
22160 }
22161
22162 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22163 if($Access ne "private")
22164 {
22165 $CheckedSymbols{"Binary"}{$S} = 1;
22166 $CheckedSymbols{"Source"}{$S} = 1;
22167 }
22168 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022169
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022170 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22171 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22172 exitReport();
22173 }
22174 }
22175 }
22176}
22177
22178sub initLogging($)
22179{
22180 my $LibVersion = $_[0];
22181 # create log directory
22182 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22183 if($OutputLogPath{$LibVersion})
22184 { # user-defined by -log-path option
22185 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22186 }
22187 if($LogMode ne "n") {
22188 mkpath($LOG_DIR);
22189 }
22190 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022191 if($Debug)
22192 { # debug directory
22193 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022194
22195 if(not $ExtraInfo)
22196 { # enable --extra-info
22197 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022199 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022200 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022201}
22202
22203sub writeLog($$)
22204{
22205 my ($LibVersion, $Msg) = @_;
22206 if($LogMode ne "n") {
22207 appendFile($LOG_PATH{$LibVersion}, $Msg);
22208 }
22209}
22210
22211sub resetLogging($)
22212{
22213 my $LibVersion = $_[0];
22214 if($LogMode!~/a|n/)
22215 { # remove old log
22216 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022217 if($Debug) {
22218 rmtree($DEBUG_PATH{$LibVersion});
22219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022220 }
22221}
22222
22223sub printErrorLog($)
22224{
22225 my $LibVersion = $_[0];
22226 if($LogMode ne "n") {
22227 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22228 }
22229}
22230
22231sub isDump($)
22232{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022233 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22234 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022235 return $1;
22236 }
22237 return 0;
22238}
22239
22240sub isDump_U($)
22241{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022242 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022243 return $1;
22244 }
22245 return 0;
22246}
22247
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022248sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022249{
22250 # read input XML descriptors or ABI dumps
22251 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022252 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022253 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022254 if(not -e $Descriptor{1}{"Path"}) {
22255 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022256 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022258 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022259 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022260 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022261 if(not -e $Descriptor{2}{"Path"}) {
22262 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022263 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022264
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022265 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022266 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022267 and isDump($Descriptor{2}{"Path"}))
22268 { # optimization: equal ABI dumps
22269 quickEmptyReports();
22270 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022271
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022272 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022273
22274 if(isDump($Descriptor{1}{"Path"})) {
22275 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022276 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022277 else {
22278 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22279 }
22280
22281 if(isDump($Descriptor{2}{"Path"})) {
22282 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22283 }
22284 else {
22285 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022286 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022287
22288 if(not $Descriptor{1}{"Version"})
22289 { # set to default: X
22290 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022291 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022292 }
22293
22294 if(not $Descriptor{2}{"Version"})
22295 { # set to default: Y
22296 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022297 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022298 }
22299
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022300 if(not $UsedDump{1}{"V"}) {
22301 initLogging(1);
22302 }
22303
22304 if(not $UsedDump{2}{"V"}) {
22305 initLogging(2);
22306 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022307
22308 # check input data
22309 if(not $Descriptor{1}{"Headers"}) {
22310 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022311 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022312 if(not $Descriptor{2}{"Headers"}) {
22313 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022314 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022315
22316 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022317 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022318 if(not $Descriptor{1}{"Libs"}) {
22319 exitStatus("Error", "can't find libraries info in descriptor d1");
22320 }
22321 if(not $Descriptor{2}{"Libs"}) {
22322 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022323 }
22324 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022325
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022326 if($UseDumps)
22327 { # --use-dumps
22328 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022329 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22330 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022331
22332 unlink($DumpPath1);
22333 unlink($DumpPath2);
22334
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022335 my $pid = fork();
22336 if($pid)
22337 { # dump on two CPU cores
22338 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22339 if($RelativeDirectory{1}) {
22340 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22341 }
22342 if($OutputLogPath{1}) {
22343 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22344 }
22345 if($CrossGcc) {
22346 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22347 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022348 if($Quiet)
22349 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022350 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022351 @PARAMS = (@PARAMS, "-logging-mode", "a");
22352 }
22353 elsif($LogMode and $LogMode ne "w")
22354 { # "w" is default
22355 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022356 }
22357 if($ExtendedCheck) {
22358 @PARAMS = (@PARAMS, "-extended");
22359 }
22360 if($UserLang) {
22361 @PARAMS = (@PARAMS, "-lang", $UserLang);
22362 }
22363 if($TargetVersion{1}) {
22364 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22365 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022366 if($BinaryOnly) {
22367 @PARAMS = (@PARAMS, "-binary");
22368 }
22369 if($SourceOnly) {
22370 @PARAMS = (@PARAMS, "-source");
22371 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022372 if($SortDump) {
22373 @PARAMS = (@PARAMS, "-sort");
22374 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022375 if($DumpFormat and $DumpFormat ne "perl") {
22376 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22377 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022378 if($CheckHeadersOnly) {
22379 @PARAMS = (@PARAMS, "-headers-only");
22380 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022381 if($Debug)
22382 {
22383 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022384 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022386 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022387 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022388 exit(1);
22389 }
22390 }
22391 else
22392 { # child
22393 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22394 if($RelativeDirectory{2}) {
22395 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22396 }
22397 if($OutputLogPath{2}) {
22398 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22399 }
22400 if($CrossGcc) {
22401 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22402 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022403 if($Quiet)
22404 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022405 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022406 @PARAMS = (@PARAMS, "-logging-mode", "a");
22407 }
22408 elsif($LogMode and $LogMode ne "w")
22409 { # "w" is default
22410 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022411 }
22412 if($ExtendedCheck) {
22413 @PARAMS = (@PARAMS, "-extended");
22414 }
22415 if($UserLang) {
22416 @PARAMS = (@PARAMS, "-lang", $UserLang);
22417 }
22418 if($TargetVersion{2}) {
22419 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22420 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022421 if($BinaryOnly) {
22422 @PARAMS = (@PARAMS, "-binary");
22423 }
22424 if($SourceOnly) {
22425 @PARAMS = (@PARAMS, "-source");
22426 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022427 if($SortDump) {
22428 @PARAMS = (@PARAMS, "-sort");
22429 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022430 if($DumpFormat and $DumpFormat ne "perl") {
22431 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22432 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022433 if($CheckHeadersOnly) {
22434 @PARAMS = (@PARAMS, "-headers-only");
22435 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022436 if($Debug)
22437 {
22438 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022439 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022441 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022442 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022443 exit(1);
22444 }
22445 else {
22446 exit(0);
22447 }
22448 }
22449 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022451 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022452 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22453 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022454 if($TargetTitle ne $TargetLibraryName) {
22455 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022456 }
22457 if($ShowRetVal) {
22458 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22459 }
22460 if($CrossGcc) {
22461 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22462 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022463 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22464 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022465 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022466 }
22467 if($ReportFormat and $ReportFormat ne "html")
22468 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022469 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22470 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022471 if($OutputReportPath) {
22472 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22473 }
22474 if($BinaryReportPath) {
22475 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22476 }
22477 if($SourceReportPath) {
22478 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22479 }
22480 if($LoggingPath) {
22481 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22482 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022483 if($CheckHeadersOnly) {
22484 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22485 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022486 if($BinaryOnly) {
22487 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22488 }
22489 if($SourceOnly) {
22490 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22491 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022492 if($Debug)
22493 {
22494 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22495 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022496 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022497 system("perl", $0, @CMP_PARAMS);
22498 exit($?>>8);
22499 }
22500 if(not $Descriptor{1}{"Dump"}
22501 or not $Descriptor{2}{"Dump"})
22502 { # need GCC toolchain to analyze
22503 # header files and libraries
22504 detect_default_paths("inc|lib|gcc");
22505 }
22506 if(not $Descriptor{1}{"Dump"})
22507 {
22508 if(not $CheckHeadersOnly) {
22509 readLibs(1);
22510 }
22511 if($CheckHeadersOnly) {
22512 setLanguage(1, "C++");
22513 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022514 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022515 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022516 }
22517 if(not $Descriptor{2}{"Dump"})
22518 {
22519 if(not $CheckHeadersOnly) {
22520 readLibs(2);
22521 }
22522 if($CheckHeadersOnly) {
22523 setLanguage(2, "C++");
22524 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022525 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022526 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022527 }
22528 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22529 { # support for old ABI dumps
22530 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022531 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022532 {
22533 $WORD_SIZE{1} = $WORD_SIZE{2};
22534 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022536 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022537 {
22538 $WORD_SIZE{2} = $WORD_SIZE{1};
22539 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22540 }
22541 }
22542 elsif(not $WORD_SIZE{1}
22543 and not $WORD_SIZE{2})
22544 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022545 $WORD_SIZE{1} = "4";
22546 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022547 }
22548 if($Descriptor{1}{"Dump"})
22549 { # support for old ABI dumps
22550 prepareTypes(1);
22551 }
22552 if($Descriptor{2}{"Dump"})
22553 { # support for old ABI dumps
22554 prepareTypes(2);
22555 }
22556 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22557 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22558 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022559 # process input data
22560 if($Descriptor{1}{"Headers"}
22561 and not $Descriptor{1}{"Dump"}) {
22562 readHeaders(1);
22563 }
22564 if($Descriptor{2}{"Headers"}
22565 and not $Descriptor{2}{"Dump"}) {
22566 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022567 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022568
22569 # clean memory
22570 %SystemHeaders = ();
22571 %mangled_name_gcc = ();
22572
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022573 prepareSymbols(1);
22574 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022575
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022576 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022577 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022578
22579 # Virtual Tables
22580 registerVTable(1);
22581 registerVTable(2);
22582
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022583 if(not checkDump(1, "1.22")
22584 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022585 { # support for old ABI dumps
22586 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22587 {
22588 if($ClassName=~/</)
22589 { # templates
22590 if(not defined $VirtualTable{1}{$ClassName})
22591 { # synchronize
22592 delete($VirtualTable{2}{$ClassName});
22593 }
22594 }
22595 }
22596 }
22597
22598 registerOverriding(1);
22599 registerOverriding(2);
22600
22601 setVirtFuncPositions(1);
22602 setVirtFuncPositions(2);
22603
22604 # Other
22605 addParamNames(1);
22606 addParamNames(2);
22607
22608 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022609}
22610
22611sub compareAPIs($)
22612{
22613 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022614
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022615 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022616 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022617
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022618 if($Level eq "Binary") {
22619 printMsg("INFO", "comparing ABIs ...");
22620 }
22621 else {
22622 printMsg("INFO", "comparing APIs ...");
22623 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022624
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022625 if($CheckHeadersOnly
22626 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022627 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022628 detectAdded_H($Level);
22629 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022630 }
22631 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022632 { # added/removed in libs
22633 detectAdded($Level);
22634 detectRemoved($Level);
22635 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022636
22637 mergeSymbols($Level);
22638 if(keys(%{$CheckedSymbols{$Level}})) {
22639 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022640 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022641
22642 $Cache{"mergeTypes"} = (); # free memory
22643
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022644 if($CheckHeadersOnly
22645 or $Level eq "Source")
22646 { # added/removed in headers
22647 mergeHeaders($Level);
22648 }
22649 else
22650 { # added/removed in libs
22651 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022652 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022653
22654 foreach my $S (keys(%{$CompatProblems{$Level}}))
22655 {
22656 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22657 {
22658 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22659 {
22660 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22661 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22662 }
22663 }
22664 }
22665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022666}
22667
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022668sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022669{
22670 my %Opts = (
22671 "OStarget"=>$OStarget,
22672 "Debug"=>$Debug,
22673 "Quiet"=>$Quiet,
22674 "LogMode"=>$LogMode,
22675 "CheckHeadersOnly"=>$CheckHeadersOnly,
22676
22677 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022678 "GCC_PATH"=>$GCC_PATH,
22679 "TargetSysInfo"=>$TargetSysInfo,
22680 "CrossPrefix"=>$CrossPrefix,
22681 "TargetLibraryName"=>$TargetLibraryName,
22682 "CrossGcc"=>$CrossGcc,
22683 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022684 "NoStdInc"=>$NoStdInc,
22685
22686 "BinaryOnly" => $BinaryOnly,
22687 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022688 );
22689 return \%Opts;
22690}
22691
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022692sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022693{
22694 my %CODE_ERROR = reverse(%ERROR_CODE);
22695 return $CODE_ERROR{$_[0]};
22696}
22697
22698sub scenario()
22699{
22700 if($StdOut)
22701 { # enable quiet mode
22702 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022703 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022704 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022705 if(not $LogMode)
22706 { # default
22707 $LogMode = "w";
22708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022709 if($UserLang)
22710 { # --lang=C++
22711 $UserLang = uc($UserLang);
22712 $COMMON_LANGUAGE{1}=$UserLang;
22713 $COMMON_LANGUAGE{2}=$UserLang;
22714 }
22715 if($LoggingPath)
22716 {
22717 $OutputLogPath{1} = $LoggingPath;
22718 $OutputLogPath{2} = $LoggingPath;
22719 if($Quiet) {
22720 $COMMON_LOG_PATH = $LoggingPath;
22721 }
22722 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022723
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022724 if($Quick) {
22725 $ADD_TMPL_INSTANCES = 0;
22726 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022727 if($OutputDumpPath)
22728 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022729 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022730 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22731 }
22732 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022733 if($BinaryOnly and $SourceOnly)
22734 { # both --binary and --source
22735 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022736 if(not $CmpSystems)
22737 {
22738 $BinaryOnly = 0;
22739 $SourceOnly = 0;
22740 }
22741
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022742 $DoubleReport = 1;
22743 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022744
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022745 if($OutputReportPath)
22746 { # --report-path
22747 $DoubleReport = 0;
22748 $JoinReport = 1;
22749 }
22750 }
22751 elsif($BinaryOnly or $SourceOnly)
22752 { # --binary or --source
22753 $DoubleReport = 0;
22754 $JoinReport = 0;
22755 }
22756 if($UseXML)
22757 { # --xml option
22758 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022759 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022761 if($ReportFormat)
22762 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022763 $ReportFormat = lc($ReportFormat);
22764 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022765 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022766 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022767 if($ReportFormat eq "htm")
22768 { # HTM == HTML
22769 $ReportFormat = "html";
22770 }
22771 elsif($ReportFormat eq "xml")
22772 { # --report-format=XML equal to --xml
22773 $UseXML = 1;
22774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022775 }
22776 else
22777 { # default: HTML
22778 $ReportFormat = "html";
22779 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022780 if($DumpFormat)
22781 { # validate
22782 $DumpFormat = lc($DumpFormat);
22783 if($DumpFormat!~/\A(xml|perl)\Z/) {
22784 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22785 }
22786 if($DumpFormat eq "xml")
22787 { # --dump-format=XML equal to --xml
22788 $UseXML = 1;
22789 }
22790 }
22791 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022792 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022793 $DumpFormat = "perl";
22794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022795 if($Quiet and $LogMode!~/a|n/)
22796 { # --quiet log
22797 if(-f $COMMON_LOG_PATH) {
22798 unlink($COMMON_LOG_PATH);
22799 }
22800 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022801 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022802 $CheckUndefined = 1;
22803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022804 if($TestTool and $UseDumps)
22805 { # --test && --use-dumps == --test-dump
22806 $TestDump = 1;
22807 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022808 if($Tolerant)
22809 { # enable all
22810 $Tolerance = 1234;
22811 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022812 if($Help)
22813 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022814 HELP_MESSAGE();
22815 exit(0);
22816 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022817 if($InfoMsg)
22818 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022819 INFO_MESSAGE();
22820 exit(0);
22821 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022822 if($ShowVersion)
22823 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022824 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 +040022825 exit(0);
22826 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022827 if($DumpVersion)
22828 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022829 printMsg("INFO", $TOOL_VERSION);
22830 exit(0);
22831 }
22832 if($ExtendedCheck) {
22833 $CheckHeadersOnly = 1;
22834 }
22835 if($SystemRoot_Opt)
22836 { # user defined root
22837 if(not -e $SystemRoot_Opt) {
22838 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22839 }
22840 $SystemRoot = $SystemRoot_Opt;
22841 $SystemRoot=~s/[\/]+\Z//g;
22842 if($SystemRoot) {
22843 $SystemRoot = get_abs_path($SystemRoot);
22844 }
22845 }
22846 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022847
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022848 if($SortDump)
22849 {
22850 $Data::Dumper::Useperl = 1;
22851 $Data::Dumper::Sortkeys = \&dump_sorting;
22852 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022853
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022854 if($TargetLibsPath)
22855 {
22856 if(not -f $TargetLibsPath) {
22857 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22858 }
22859 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22860 $TargetLibs{$Lib} = 1;
22861 }
22862 }
22863 if($TargetHeadersPath)
22864 { # --headers-list
22865 if(not -f $TargetHeadersPath) {
22866 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22867 }
22868 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22869 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022870 $TargetHeaders{1}{get_filename($Header)} = 1;
22871 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022872 }
22873 }
22874 if($TargetHeader)
22875 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022876 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22877 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022878 }
22879 if($TestTool
22880 or $TestDump)
22881 { # --test, --test-dump
22882 detect_default_paths("bin|gcc"); # to compile libs
22883 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022884 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030022885 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022886 exit(0);
22887 }
22888 if($DumpSystem)
22889 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022890
22891 if(not $TargetSysInfo) {
22892 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22893 }
22894
22895 if(not -d $TargetSysInfo) {
22896 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22897 }
22898
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022899 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022900 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022901 { # system XML descriptor
22902 if(not -f $DumpSystem) {
22903 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22904 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022905
22906 my $SDesc = readFile($DumpSystem);
22907 if(my $RelDir = $RelativeDirectory{1}) {
22908 $SDesc =~ s/{RELPATH}/$RelDir/g;
22909 }
22910
22911 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022912 foreach (@{$Ret->{"Tools"}})
22913 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022914 push_U($SystemPaths{"bin"}, $_);
22915 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022916 }
22917 if($Ret->{"CrossPrefix"}) {
22918 $CrossPrefix = $Ret->{"CrossPrefix"};
22919 }
22920 }
22921 elsif($SystemRoot_Opt)
22922 { # -sysroot "/" option
22923 # default target: /usr/lib, /usr/include
22924 # search libs: /usr/lib and /lib
22925 if(not -e $SystemRoot."/usr/lib") {
22926 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22927 }
22928 if(not -e $SystemRoot."/lib") {
22929 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22930 }
22931 if(not -e $SystemRoot."/usr/include") {
22932 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22933 }
22934 readSystemDescriptor("
22935 <name>
22936 $DumpSystem
22937 </name>
22938 <headers>
22939 $SystemRoot/usr/include
22940 </headers>
22941 <libs>
22942 $SystemRoot/usr/lib
22943 </libs>
22944 <search_libs>
22945 $SystemRoot/lib
22946 </search_libs>");
22947 }
22948 else {
22949 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22950 }
22951 detect_default_paths("bin|gcc"); # to check symbols
22952 if($OStarget eq "windows")
22953 { # to run dumpbin.exe
22954 # and undname.exe
22955 check_win32_env();
22956 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022957 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022958 exit(0);
22959 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022961 if($CmpSystems)
22962 { # --cmp-systems
22963 detect_default_paths("bin"); # to extract dumps
22964 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022965 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022966 exit(0);
22967 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022968
22969 if(not $CountSymbols)
22970 {
22971 if(not $TargetLibraryName) {
22972 exitStatus("Error", "library name is not selected (-l option)");
22973 }
22974 else
22975 { # validate library name
22976 if($TargetLibraryName=~/[\*\/\\]/) {
22977 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022979 }
22980 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022981
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022982 if(not $TargetTitle) {
22983 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022984 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022986 if($SymbolsListPath)
22987 {
22988 if(not -f $SymbolsListPath) {
22989 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22990 }
22991 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22992 $SymbolsList{$Interface} = 1;
22993 }
22994 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022995 if($TypesListPath)
22996 {
22997 if(not -f $TypesListPath) {
22998 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22999 }
23000 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
23001 $TypesList{$Type} = 1;
23002 }
23003 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023004 if($SkipSymbolsListPath)
23005 {
23006 if(not -f $SkipSymbolsListPath) {
23007 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23008 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023009 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23010 {
23011 $SkipSymbols{1}{$Interface} = 1;
23012 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023013 }
23014 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023015 if($SkipTypesListPath)
23016 {
23017 if(not -f $SkipTypesListPath) {
23018 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23019 }
23020 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23021 {
23022 $SkipTypes{1}{$Type} = 1;
23023 $SkipTypes{2}{$Type} = 1;
23024 }
23025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023026 if($SkipHeadersPath)
23027 {
23028 if(not -f $SkipHeadersPath) {
23029 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23030 }
23031 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023032 { # register for both versions
23033 $SkipHeadersList{1}{$Path} = 1;
23034 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023036 my ($CPath, $Type) = classifyPath($Path);
23037 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023038 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023039 }
23040 }
23041 if($ParamNamesPath)
23042 {
23043 if(not -f $ParamNamesPath) {
23044 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23045 }
23046 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23047 {
23048 if($Line=~s/\A(\w+)\;//)
23049 {
23050 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023051 if($Line=~/;(\d+);/)
23052 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023053 while($Line=~s/(\d+);(\w+)//) {
23054 $AddIntParams{$Interface}{$1}=$2;
23055 }
23056 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023057 else
23058 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023059 my $Num = 0;
23060 foreach my $Name (split(/;/, $Line)) {
23061 $AddIntParams{$Interface}{$Num++}=$Name;
23062 }
23063 }
23064 }
23065 }
23066 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023068 if($AppPath)
23069 {
23070 if(not -f $AppPath) {
23071 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23072 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023073
23074 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023075 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023076 $SymbolsList_App{$Interface} = 1;
23077 }
23078 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023079
23080 if($CountSymbols)
23081 {
23082 if(not -e $CountSymbols) {
23083 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23084 }
23085
23086 read_ABI_Dump(1, $CountSymbols);
23087
23088 foreach my $Id (keys(%{$SymbolInfo{1}}))
23089 {
23090 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23091 if(not $MnglName) {
23092 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23093 }
23094
23095 if(my $SV = $SymVer{1}{$MnglName}) {
23096 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23097 }
23098 else {
23099 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23100 }
23101
23102 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23103 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23104 }
23105 }
23106
23107 my $Count = 0;
23108 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23109 {
23110 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23111 next;
23112 }
23113 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23114 next;
23115 }
23116 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23117 next;
23118 }
23119
23120 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23121 }
23122
23123 printMsg("INFO", $Count);
23124 exit(0);
23125 }
23126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023127 if($DumpAPI)
23128 { # --dump-abi
23129 # make an API dump
23130 create_ABI_Dump();
23131 exit($COMPILE_ERRORS);
23132 }
23133 # default: compare APIs
23134 # -d1 <path>
23135 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023136 compareInit();
23137 if($JoinReport or $DoubleReport)
23138 {
23139 compareAPIs("Binary");
23140 compareAPIs("Source");
23141 }
23142 elsif($BinaryOnly) {
23143 compareAPIs("Binary");
23144 }
23145 elsif($SourceOnly) {
23146 compareAPIs("Source");
23147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023148 exitReport();
23149}
23150
23151scenario();