blob: 4b2b41f7def0e541aebc1d9b7e35c604b0076c9e [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03003# ABI Compliance Checker (ABICC) 1.99.18
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 Ponomarenko9e05bee2016-04-03 15:57:20 +030063my $TOOL_VERSION = "1.99.18";
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 Ponomarenkoe3419b42016-01-28 15:06:08 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI);
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 Ponomarenkoab282102012-03-11 11:57:02 +0400224# other options
225 "test!" => \$TestTool,
226 "test-dump!" => \$TestDump,
227 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400228 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400229 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "p|params=s" => \$ParamNamesPath,
231 "relpath1|relpath=s" => \$RelativeDirectory{1},
232 "relpath2=s" => \$RelativeDirectory{2},
233 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400234 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400235 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400236 "bin-report-path=s" => \$BinaryReportPath,
237 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "log-path=s" => \$LoggingPath,
239 "log1-path=s" => \$OutputLogPath{1},
240 "log2-path=s" => \$OutputLogPath{2},
241 "logging-mode=s" => \$LogMode,
242 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300243 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400244 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400245 "extra-info=s" => \$ExtraInfo,
246 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400247 "force!" => \$Force,
248 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400249 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400250 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400251 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400252 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300253 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
254 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300255 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400256) or ERR_MESSAGE();
257
258sub ERR_MESSAGE()
259{
260 printMsg("INFO", "\n".$ShortUsage);
261 exit($ERROR_CODE{"Error"});
262}
263
264my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
265my $SLIB_TYPE = $LIB_TYPE;
266if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
267{ # show as "shared" library
268 $SLIB_TYPE = "shared";
269}
270my $LIB_EXT = getLIB_EXT($OSgroup);
271my $AR_EXT = getAR_EXT($OSgroup);
272my $BYTE_SIZE = 8;
273my $COMMON_LOG_PATH = "logs/run.log";
274
275my $HelpMessage="
276NAME:
277 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400278 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400279
280DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400281 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400282 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
283 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
284 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
285 and/or source-level compatibility: changes in calling stack, v-table changes,
286 removed symbols, renamed fields, etc. Binary incompatibility may result in
287 crashing or incorrect behavior of applications built with an old version of
288 a library if they run on a new one. Source incompatibility may result in
289 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400290
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400291 The tool is intended for developers of software libraries and maintainers
292 of operating systems who are interested in ensuring backward compatibility,
293 i.e. allow old applications to run or to be recompiled with newer library
294 versions.
295
296 Also the tool can be used by ISVs for checking applications portability to
297 new library versions. Found issues can be taken into account when adapting
298 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400299
300 This tool is free software: you can redistribute it and/or modify it
301 under the terms of the GNU LGPL or GNU GPL.
302
303USAGE:
304 $CmdName [options]
305
306EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400307 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400308
309 OLD.xml and NEW.xml are XML-descriptors:
310
311 <version>
312 1.0
313 </version>
314
315 <headers>
316 /path1/to/header(s)/
317 /path2/to/header(s)/
318 ...
319 </headers>
320
321 <libs>
322 /path1/to/library(ies)/
323 /path2/to/library(ies)/
324 ...
325 </libs>
326
327INFORMATION OPTIONS:
328 -h|-help
329 Print this help.
330
331 -i|-info
332 Print complete info.
333
334 -v|-version
335 Print version information.
336
337 -dumpversion
338 Print the tool version ($TOOL_VERSION) and don't do anything else.
339
340GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400341 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400342 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400343
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400344 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400345 Descriptor of 1st (old) library version.
346 It may be one of the following:
347
348 1. XML-descriptor (VERSION.xml file):
349
350 <version>
351 1.0
352 </version>
353
354 <headers>
355 /path1/to/header(s)/
356 /path2/to/header(s)/
357 ...
358 </headers>
359
360 <libs>
361 /path1/to/library(ies)/
362 /path2/to/library(ies)/
363 ...
364 </libs>
365
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300366 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367
368 2. ABI dump generated by -dump option
369 3. Directory with headers and/or $SLIB_TYPE libraries
370 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300372 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400373 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400374
375 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400376 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400377
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400378 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400379 Descriptor of 2nd (new) library version.
380
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400381 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400382 Create library ABI dump for the input XML descriptor. You can
383 transfer it anywhere and pass instead of the descriptor. Also
384 it can be used for debugging the tool.
385
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300386 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400387
388sub HELP_MESSAGE() {
389 printMsg("INFO", $HelpMessage."
390MORE INFO:
391 $CmdName --info\n");
392}
393
394sub INFO_MESSAGE()
395{
396 printMsg("INFO", "$HelpMessage
397EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400398 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300399 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400400 for portability to the new library version.
401
402 -static-libs
403 Check static libraries instead of the shared ones. The <libs> section
404 of the XML-descriptor should point to static libraries location.
405
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300406 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400407 Path to the cross GCC compiler to use instead of the usual (host) GCC.
408
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300409 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300411
412 -gcc-options OPTS
413 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400415 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400416 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400417 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400419 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400420 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200421 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422
423 In general case you should specify it in the XML-descriptor:
424 <version>
425 VERSION
426 </version>
427
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400428 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429 Specify 2nd library version outside the descriptor.
430
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400431 -vnum NUM
432 Specify the library version in the generated ABI dump. The <version> section
433 of the input XML descriptor will be overwritten in this case.
434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 -s|-strict
436 Treat all compatibility warnings as problems. Add a number of \"Low\"
437 severity problems to the return value of the tool.
438
439 -headers-only
440 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
441 provide a low quality compatibility report with false positives and
442 without detecting of added/removed symbols.
443
444 Alternatively you can write \"none\" word to the <libs> section
445 in the XML-descriptor:
446 <libs>
447 none
448 </libs>
449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 -show-retval
451 Show the symbol's return type in the report.
452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400453 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300454 This option allows to specify a file with a list of symbols (mangled
455 names in C++) that should be checked. Other symbols will not be checked.
456
457 -types-list PATH
458 This option allows to specify a file with a list of types that should
459 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400460
461 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300462 The list of symbols that should not be checked.
463
464 -skip-types PATH
465 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400466
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400467 -headers-list PATH
468 The file with a list of headers, that should be checked/dumped.
469
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400470 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400471 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400472
473 -header NAME
474 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400475
476 -use-dumps
477 Make dumps for two versions of a library and compare dumps. This should
478 increase the performance of the tool and decrease the system memory usage.
479
480 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400481 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400482
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400483 -dump-system NAME -sysroot DIR
484 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400485 create XML descriptors and make ABI dumps for each library. The result
486 set of ABI dumps can be compared (--cmp-systems) with the other one
487 created for other version of operating system in order to check them for
488 compatibility. Do not forget to specify -cross-gcc option if your target
489 system requires some specific version of GCC compiler (different from
490 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400491 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400492
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400493 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400494 The same as the previous option but takes an XML descriptor of the target
495 system as input, where you should describe it:
496
497 /* Primary sections */
498
499 <name>
500 /* Name of the system */
501 </name>
502
503 <headers>
504 /* The list of paths to header files and/or
505 directories with header files, one per line */
506 </headers>
507
508 <libs>
509 /* The list of paths to shared libraries and/or
510 directories with shared libraries, one per line */
511 </libs>
512
513 /* Optional sections */
514
515 <search_headers>
516 /* List of directories to be searched
517 for header files to automatically
518 generate include paths, one per line */
519 </search_headers>
520
521 <search_libs>
522 /* List of directories to be searched
523 for shared libraries to resolve
524 dependencies, one per line */
525 </search_libs>
526
527 <tools>
528 /* List of directories with tools used
529 for analysis (GCC toolchain), one per line */
530 </tools>
531
532 <cross_prefix>
533 /* GCC toolchain prefix.
534 Examples:
535 arm-linux-gnueabi
536 arm-none-symbianelf */
537 </cross_prefix>
538
539 <gcc_options>
540 /* Additional GCC options, one per line */
541 </gcc_options>
542
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400543 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300544 This option should be used with -dump-system option to dump
545 ABI of operating systems and configure the dumping process.
546 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400547 modules/Targets/{unix, symbian, windows}
548
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 Ponomarenko1bdef342012-03-19 17:23:47 +0400616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400617OTHER OPTIONS:
618 -test
619 Run internal tests. Create two binary incompatible versions of a sample
620 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300621 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400622
623 -test-dump
624 Test ability to create, read and compare ABI dumps.
625
626 -debug
627 Debugging mode. Print debug info on the screen. Save intermediate
628 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400629 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400630
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631 Also consider using --dump option for debugging the tool.
632
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400633 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400634 If your header files are written in C language and can be compiled
635 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
636 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400637
638 -cpp-incompatible
639 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400640
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400641 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400642 Path to file with the function parameter names. It can be used
643 for improving report view if the library header files have no
644 parameter names. File format:
645
646 func1;param1;param2;param3 ...
647 func2;param1;param2;param3 ...
648 ...
649
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400650 -relpath PATH
651 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400652 for dumping the library ABI (see -dump option).
653
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400654 -relpath1 PATH
655 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 -relpath2 PATH
658 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400660 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400661 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400663 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400664
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400665 -sort
666 Enable sorting of data in ABI dumps.
667
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400668 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400669 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400670 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400672
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400673 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400674 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400675 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400676 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400677
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400679 Path to \"Source\" compatibility report.
680 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400682
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400684 Log path for all messages.
685 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400686 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400687
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689 Log path for 1st version of a library.
690 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694 Log path for 2nd version of a library.
695 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699 Change logging mode.
700 Modes:
701 w - overwrite old logs (default)
702 a - append old logs
703 n - do not write any logs
704
705 -list-affected
706 Generate file with the list of incompatible
707 symbols beside the HTML compatibility report.
708 Use 'c++filt \@file' command from GNU binutils
709 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400710 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400712 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400713
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 The component name in the title and summary of the HTML report.
716 Default:
717 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300718
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300719 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400722
723 -extra-info DIR
724 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400725
726 -extra-dump
727 Create extended ABI dump containing all symbols
728 from the translation unit.
729
730 -force
731 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400732
733 -tolerance LEVEL
734 Apply a set of heuristics to successfully compile input
735 header files. You can enable several tolerance levels by
736 joining them into one string (e.g. 13, 124, etc.).
737 Levels:
738 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
739 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
740 3 - skip headers that iclude non-Linux headers
741 4 - skip headers included by others
742
743 -tolerant
744 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400745
746 -check
747 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400748
749 -quick
750 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400751
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300752 -skip-internal-symbols PATTERN
753 Do not check symbols matched by the pattern.
754
755 -skip-internal-types PATTERN
756 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300757
758 -check-private-abi
759 Check data types from the private part of the ABI when
760 comparing ABI dumps created by the ABI Dumper tool with
761 use of the -public-headers option.
762
763 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400765REPORT:
766 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400767 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400768
769 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400770 logs/LIB_NAME/V1/log.txt
771 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400772
773EXIT CODES:
774 0 - Compatible. The tool has run without any errors.
775 non-zero - Incompatible or the tool has run with errors.
776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400777MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300778 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400779}
780
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400781my %Operator_Indication = (
782 "not" => "~",
783 "assign" => "=",
784 "andassign" => "&=",
785 "orassign" => "|=",
786 "xorassign" => "^=",
787 "or" => "|",
788 "xor" => "^",
789 "addr" => "&",
790 "and" => "&",
791 "lnot" => "!",
792 "eq" => "==",
793 "ne" => "!=",
794 "lt" => "<",
795 "lshift" => "<<",
796 "lshiftassign" => "<<=",
797 "rshiftassign" => ">>=",
798 "call" => "()",
799 "mod" => "%",
800 "modassign" => "%=",
801 "subs" => "[]",
802 "land" => "&&",
803 "lor" => "||",
804 "rshift" => ">>",
805 "ref" => "->",
806 "le" => "<=",
807 "deref" => "*",
808 "mult" => "*",
809 "preinc" => "++",
810 "delete" => " delete",
811 "vecnew" => " new[]",
812 "vecdelete" => " delete[]",
813 "predec" => "--",
814 "postinc" => "++",
815 "postdec" => "--",
816 "plusassign" => "+=",
817 "plus" => "+",
818 "minus" => "-",
819 "minusassign" => "-=",
820 "gt" => ">",
821 "ge" => ">=",
822 "new" => " new",
823 "multassign" => "*=",
824 "divassign" => "/=",
825 "div" => "/",
826 "neg" => "-",
827 "pos" => "+",
828 "memref" => "->*",
829 "compound" => "," );
830
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400831my %UnknownOperator;
832
833my %NodeType= (
834 "array_type" => "Array",
835 "binfo" => "Other",
836 "boolean_type" => "Intrinsic",
837 "complex_type" => "Intrinsic",
838 "const_decl" => "Other",
839 "enumeral_type" => "Enum",
840 "field_decl" => "Other",
841 "function_decl" => "Other",
842 "function_type" => "FunctionType",
843 "identifier_node" => "Other",
844 "integer_cst" => "Other",
845 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400846 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400847 "method_type" => "MethodType",
848 "namespace_decl" => "Other",
849 "parm_decl" => "Other",
850 "pointer_type" => "Pointer",
851 "real_cst" => "Other",
852 "real_type" => "Intrinsic",
853 "record_type" => "Struct",
854 "reference_type" => "Ref",
855 "string_cst" => "Other",
856 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400857 "template_type_parm" => "TemplateParam",
858 "typename_type" => "TypeName",
859 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400860 "tree_list" => "Other",
861 "tree_vec" => "Other",
862 "type_decl" => "Other",
863 "union_type" => "Union",
864 "var_decl" => "Other",
865 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400866 "nop_expr" => "Other", #
867 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400868 "offset_type" => "Other" );
869
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400870my %CppKeywords_C = map {$_=>1} (
871 # C++ 2003 keywords
872 "public",
873 "protected",
874 "private",
875 "default",
876 "template",
877 "new",
878 #"asm",
879 "dynamic_cast",
880 "auto",
881 "try",
882 "namespace",
883 "typename",
884 "using",
885 "reinterpret_cast",
886 "friend",
887 "class",
888 "virtual",
889 "const_cast",
890 "mutable",
891 "static_cast",
892 "export",
893 # C++0x keywords
894 "noexcept",
895 "nullptr",
896 "constexpr",
897 "static_assert",
898 "explicit",
899 # cannot be used as a macro name
900 # as it is an operator in C++
901 "and",
902 #"and_eq",
903 "not",
904 #"not_eq",
905 "or"
906 #"or_eq",
907 #"bitand",
908 #"bitor",
909 #"xor",
910 #"xor_eq",
911 #"compl"
912);
913
914my %CppKeywords_F = map {$_=>1} (
915 "delete",
916 "catch",
917 "alignof",
918 "thread_local",
919 "decltype",
920 "typeid"
921);
922
923my %CppKeywords_O = map {$_=>1} (
924 "bool",
925 "register",
926 "inline",
927 "operator"
928);
929
930my %CppKeywords_A = map {$_=>1} (
931 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400932 "throw",
933 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400934);
935
936foreach (keys(%CppKeywords_C),
937keys(%CppKeywords_F),
938keys(%CppKeywords_O)) {
939 $CppKeywords_A{$_}=1;
940}
941
942# Header file extensions as described by gcc
943my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
944
945my %IntrinsicMangling = (
946 "void" => "v",
947 "bool" => "b",
948 "wchar_t" => "w",
949 "char" => "c",
950 "signed char" => "a",
951 "unsigned char" => "h",
952 "short" => "s",
953 "unsigned short" => "t",
954 "int" => "i",
955 "unsigned int" => "j",
956 "long" => "l",
957 "unsigned long" => "m",
958 "long long" => "x",
959 "__int64" => "x",
960 "unsigned long long" => "y",
961 "__int128" => "n",
962 "unsigned __int128" => "o",
963 "float" => "f",
964 "double" => "d",
965 "long double" => "e",
966 "__float80" => "e",
967 "__float128" => "g",
968 "..." => "z"
969);
970
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400971my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400973my %StdcxxMangling = (
974 "3std"=>"St",
975 "3std9allocator"=>"Sa",
976 "3std12basic_string"=>"Sb",
977 "3std12basic_stringIcE"=>"Ss",
978 "3std13basic_istreamIcE"=>"Si",
979 "3std13basic_ostreamIcE"=>"So",
980 "3std14basic_iostreamIcE"=>"Sd"
981);
982
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400983my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400984my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
985
986my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400987my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400989my %ConstantSuffix = (
990 "unsigned int"=>"u",
991 "long"=>"l",
992 "unsigned long"=>"ul",
993 "long long"=>"ll",
994 "unsigned long long"=>"ull"
995);
996
997my %ConstantSuffixR =
998reverse(%ConstantSuffix);
999
1000my %OperatorMangling = (
1001 "~" => "co",
1002 "=" => "aS",
1003 "|" => "or",
1004 "^" => "eo",
1005 "&" => "an",#ad (addr)
1006 "==" => "eq",
1007 "!" => "nt",
1008 "!=" => "ne",
1009 "<" => "lt",
1010 "<=" => "le",
1011 "<<" => "ls",
1012 "<<=" => "lS",
1013 ">" => "gt",
1014 ">=" => "ge",
1015 ">>" => "rs",
1016 ">>=" => "rS",
1017 "()" => "cl",
1018 "%" => "rm",
1019 "[]" => "ix",
1020 "&&" => "aa",
1021 "||" => "oo",
1022 "*" => "ml",#de (deref)
1023 "++" => "pp",#
1024 "--" => "mm",#
1025 "new" => "nw",
1026 "delete" => "dl",
1027 "new[]" => "na",
1028 "delete[]" => "da",
1029 "+=" => "pL",
1030 "+" => "pl",#ps (pos)
1031 "-" => "mi",#ng (neg)
1032 "-=" => "mI",
1033 "*=" => "mL",
1034 "/=" => "dV",
1035 "&=" => "aN",
1036 "|=" => "oR",
1037 "%=" => "rM",
1038 "^=" => "eO",
1039 "/" => "dv",
1040 "->*" => "pm",
1041 "->" => "pt",#rf (ref)
1042 "," => "cm",
1043 "?" => "qu",
1044 "." => "dt",
1045 "sizeof"=> "sz"#st
1046);
1047
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001048my %Intrinsic_Keywords = map {$_=>1} (
1049 "true",
1050 "false",
1051 "_Bool",
1052 "_Complex",
1053 "const",
1054 "int",
1055 "long",
1056 "void",
1057 "short",
1058 "float",
1059 "volatile",
1060 "restrict",
1061 "unsigned",
1062 "signed",
1063 "char",
1064 "double",
1065 "class",
1066 "struct",
1067 "union",
1068 "enum"
1069);
1070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001071my %GlibcHeader = map {$_=>1} (
1072 "aliases.h",
1073 "argp.h",
1074 "argz.h",
1075 "assert.h",
1076 "cpio.h",
1077 "ctype.h",
1078 "dirent.h",
1079 "envz.h",
1080 "errno.h",
1081 "error.h",
1082 "execinfo.h",
1083 "fcntl.h",
1084 "fstab.h",
1085 "ftw.h",
1086 "glob.h",
1087 "grp.h",
1088 "iconv.h",
1089 "ifaddrs.h",
1090 "inttypes.h",
1091 "langinfo.h",
1092 "limits.h",
1093 "link.h",
1094 "locale.h",
1095 "malloc.h",
1096 "math.h",
1097 "mntent.h",
1098 "monetary.h",
1099 "nl_types.h",
1100 "obstack.h",
1101 "printf.h",
1102 "pwd.h",
1103 "regex.h",
1104 "sched.h",
1105 "search.h",
1106 "setjmp.h",
1107 "shadow.h",
1108 "signal.h",
1109 "spawn.h",
1110 "stdarg.h",
1111 "stdint.h",
1112 "stdio.h",
1113 "stdlib.h",
1114 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001115 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001116 "tar.h",
1117 "termios.h",
1118 "time.h",
1119 "ulimit.h",
1120 "unistd.h",
1121 "utime.h",
1122 "wchar.h",
1123 "wctype.h",
1124 "wordexp.h" );
1125
1126my %GlibcDir = map {$_=>1} (
1127 "arpa",
1128 "bits",
1129 "gnu",
1130 "netinet",
1131 "net",
1132 "nfs",
1133 "rpc",
1134 "sys",
1135 "linux" );
1136
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001137my %WinHeaders = map {$_=>1} (
1138 "dos.h",
1139 "process.h",
1140 "winsock.h",
1141 "config-win.h",
1142 "mem.h",
1143 "windows.h",
1144 "winsock2.h",
1145 "crtdbg.h",
1146 "ws2tcpip.h"
1147);
1148
1149my %ObsoleteHeaders = map {$_=>1} (
1150 "iostream.h",
1151 "fstream.h"
1152);
1153
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001154my %AlienHeaders = map {$_=>1} (
1155 # Solaris
1156 "thread.h",
1157 "sys/atomic.h",
1158 # HPUX
1159 "sys/stream.h",
1160 # Symbian
1161 "AknDoc.h",
1162 # Atari ST
1163 "ext.h",
1164 "tos.h",
1165 # MS-DOS
1166 "alloc.h",
1167 # Sparc
1168 "sys/atomic.h"
1169);
1170
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001171my %ConfHeaders = map {$_=>1} (
1172 "atomic",
1173 "conf.h",
1174 "config.h",
1175 "configure.h",
1176 "build.h",
1177 "setup.h"
1178);
1179
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001180my %LocalIncludes = map {$_=>1} (
1181 "/usr/local/include",
1182 "/usr/local" );
1183
1184my %OS_AddPath=(
1185# These paths are needed if the tool cannot detect them automatically
1186 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001187 "include"=>[
1188 "/Library",
1189 "/Developer/usr/include"
1190 ],
1191 "lib"=>[
1192 "/Library",
1193 "/Developer/usr/lib"
1194 ],
1195 "bin"=>[
1196 "/Developer/usr/bin"
1197 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001198 },
1199 "beos"=>{
1200 # Haiku has GCC 2.95.3 by default
1201 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001202 "include"=>[
1203 "/boot/common",
1204 "/boot/develop"
1205 ],
1206 "lib"=>[
1207 "/boot/common/lib",
1208 "/boot/system/lib",
1209 "/boot/apps"
1210 ],
1211 "bin"=>[
1212 "/boot/common/bin",
1213 "/boot/system/bin",
1214 "/boot/develop/abi"
1215 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001217);
1218
1219my %Slash_Type=(
1220 "default"=>"/",
1221 "windows"=>"\\"
1222);
1223
1224my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1225
1226# Global Variables
1227my %COMMON_LANGUAGE=(
1228 1 => "C",
1229 2 => "C" );
1230
1231my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001232my $MAX_CPPFILT_FILE_SIZE = 50000;
1233my $CPPFILT_SUPPORT_FILE;
1234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001235my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001237my $STDCXX_TESTING = 0;
1238my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001239my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001240
1241my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001242my $CheckUndefined = 0;
1243
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001244my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001245if($TargetComponent_Opt) {
1246 $TargetComponent = lc($TargetComponent_Opt);
1247}
1248else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001249{ # default: library
1250 # other components: header, system, ...
1251 $TargetComponent = "library";
1252}
1253
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001254my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001255
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001256my $SystemRoot;
1257
1258my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001259my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001260my %LOG_PATH;
1261my %DEBUG_PATH;
1262my %Cache;
1263my %LibInfo;
1264my $COMPILE_ERRORS = 0;
1265my %CompilerOptions;
1266my %CheckedDyLib;
1267my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1268
1269# Constants (#defines)
1270my %Constants;
1271my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001272my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001273
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001274# Extra Info
1275my %SymbolHeader;
1276my %KnownLibs;
1277
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001278# Templates
1279my %TemplateInstance;
1280my %BasicTemplate;
1281my %TemplateArg;
1282my %TemplateDecl;
1283my %TemplateMap;
1284
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001285# Types
1286my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287my %SkipTypes = (
1288 "1"=>{},
1289 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001290my %CheckedTypes;
1291my %TName_Tid;
1292my %EnumMembName_Id;
1293my %NestedNameSpaces = (
1294 "1"=>{},
1295 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001296my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001297my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001298my %ClassVTable;
1299my %ClassVTable_Content;
1300my %VTableClass;
1301my %AllocableClass;
1302my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001303my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001304my %Class_SubClasses;
1305my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001306my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001307my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001308
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001309my %CheckedTypeInfo;
1310
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001311# Typedefs
1312my %Typedef_BaseName;
1313my %Typedef_Tr;
1314my %Typedef_Eq;
1315my %StdCxxTypedef;
1316my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001317my %MissedBase;
1318my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001319my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001320
1321# Symbols
1322my %SymbolInfo;
1323my %tr_name;
1324my %mangled_name_gcc;
1325my %mangled_name;
1326my %SkipSymbols = (
1327 "1"=>{},
1328 "2"=>{} );
1329my %SkipNameSpaces = (
1330 "1"=>{},
1331 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001332my %AddNameSpaces = (
1333 "1"=>{},
1334 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001335my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001336my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001337my %SymbolsList_App;
1338my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001339my %Symbol_Library = (
1340 "1"=>{},
1341 "2"=>{} );
1342my %Library_Symbol = (
1343 "1"=>{},
1344 "2"=>{} );
1345my %DepSymbol_Library = (
1346 "1"=>{},
1347 "2"=>{} );
1348my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349 "1"=>{},
1350 "2"=>{} );
1351my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001352my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001353my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001354my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001355my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001356my %Library_Needed= (
1357 "1"=>{},
1358 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001359
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001360# Extra Info
1361my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001362my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001364# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001365my %Include_Preamble = (
1366 "1"=>[],
1367 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001368my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001369my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001370my %HeaderName_Paths;
1371my %Header_Dependency;
1372my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001373my %Include_Paths = (
1374 "1"=>[],
1375 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376my %INC_PATH_AUTODETECT = (
1377 "1"=>1,
1378 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001379my %Add_Include_Paths = (
1380 "1"=>[],
1381 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001382my %Skip_Include_Paths;
1383my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384my %Header_ErrorRedirect;
1385my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001386my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001387my %Header_ShouldNotBeUsed;
1388my %RecursiveIncludes;
1389my %Header_Include_Prefix;
1390my %SkipHeaders;
1391my %SkipHeadersList=(
1392 "1"=>{},
1393 "2"=>{} );
1394my %SkipLibs;
1395my %Include_Order;
1396my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001397my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001398my %TUnit_Funcs;
1399my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001401my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402 "1"=>0,
1403 "2"=>0 );
1404my %AutoPreambleMode = (
1405 "1"=>0,
1406 "2"=>0 );
1407my %MinGWMode = (
1408 "1"=>0,
1409 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001410my %Cpp0xMode = (
1411 "1"=>0,
1412 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413
1414# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001415my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001416my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001417my %RegisteredSONAMEs;
1418my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001419
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001420my %CheckedArch;
1421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422# System Objects
1423my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001424my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001425my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001426
1427# System Headers
1428my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001429my @DefaultCppPaths;
1430my @DefaultGccPaths;
1431my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001432my %DefaultCppHeader;
1433my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001434my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001435
1436# Merging
1437my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438my $Version;
1439my %AddedInt;
1440my %RemovedInt;
1441my %AddedInt_Virt;
1442my %RemovedInt_Virt;
1443my %VirtualReplacement;
1444my %ChangedTypedef;
1445my %CompatRules;
1446my %IncompleteRules;
1447my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001448my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001449my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001450my %ReturnedClass;
1451my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001452my %SourceAlternative;
1453my %SourceAlternative_B;
1454my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001455my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001456
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001457# Calling Conventions
1458my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001459 1=>{ "R"=>0, "P"=>0 },
1460 2=>{ "R"=>0, "P"=>0 }
1461);
1462
1463# ABI Dump
1464my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001465
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001466# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001467my %TargetLibs;
1468my %TargetHeaders;
1469
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001470# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471my $OStarget = $OSgroup;
1472my %TargetTools;
1473
1474# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001475my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001476
1477# Recursion locks
1478my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001479my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001480my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001481my @RecurInclude;
1482my @RecurConstant;
1483
1484# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001485my %SystemPaths = (
1486 "include"=>[],
1487 "lib"=>[],
1488 "bin"=>[]
1489);
1490my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my $GCC_PATH;
1492
1493# Symbols versioning
1494my %SymVer = (
1495 "1"=>{},
1496 "2"=>{} );
1497
1498# Problem descriptions
1499my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001500my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001501my %TotalAffected;
1502
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001503# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001504my $ContentID = 1;
1505my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001506my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1507my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001508my $ContentSpanEnd = "</span>\n";
1509my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1510my $ContentDivEnd = "</div>\n";
1511my $Content_Counter = 0;
1512
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001513# Modes
1514my $JoinReport = 1;
1515my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001516
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001517my %Severity_Val=(
1518 "High"=>3,
1519 "Medium"=>2,
1520 "Low"=>1,
1521 "Safe"=>-1
1522);
1523
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001524sub get_Modules()
1525{
1526 my $TOOL_DIR = get_dirname($0);
1527 if(not $TOOL_DIR)
1528 { # patch for MS Windows
1529 $TOOL_DIR = ".";
1530 }
1531 my @SEARCH_DIRS = (
1532 # tool's directory
1533 abs_path($TOOL_DIR),
1534 # relative path to modules
1535 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001536 # install path
1537 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001538 );
1539 foreach my $DIR (@SEARCH_DIRS)
1540 {
1541 if(not is_abs($DIR))
1542 { # relative path
1543 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1544 }
1545 if(-d $DIR."/modules") {
1546 return $DIR."/modules";
1547 }
1548 }
1549 exitStatus("Module_Error", "can't find modules");
1550}
1551
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001552my %LoadedModules = ();
1553
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001554sub loadModule($)
1555{
1556 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001557 if(defined $LoadedModules{$Name}) {
1558 return;
1559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001560 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1561 if(not -f $Path) {
1562 exitStatus("Module_Error", "can't access \'$Path\'");
1563 }
1564 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001565 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001566}
1567
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001568sub readModule($$)
1569{
1570 my ($Module, $Name) = @_;
1571 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1572 if(not -f $Path) {
1573 exitStatus("Module_Error", "can't access \'$Path\'");
1574 }
1575 return readFile($Path);
1576}
1577
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001578sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001580 my $Number = $_[0];
1581 if(not $Number) {
1582 $Number = 1;
1583 }
1584 else {
1585 $Number = int($Number)+1;
1586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001587 if($Number>3) {
1588 return $Number."th";
1589 }
1590 elsif($Number==1) {
1591 return "1st";
1592 }
1593 elsif($Number==2) {
1594 return "2nd";
1595 }
1596 elsif($Number==3) {
1597 return "3rd";
1598 }
1599 else {
1600 return $Number;
1601 }
1602}
1603
1604sub search_Tools($)
1605{
1606 my $Name = $_[0];
1607 return "" if(not $Name);
1608 if(my @Paths = keys(%TargetTools))
1609 {
1610 foreach my $Path (@Paths)
1611 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001612 if(-f join_P($Path, $Name)) {
1613 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001614 }
1615 if($CrossPrefix)
1616 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001617 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001618 if(-f $Candidate) {
1619 return $Candidate;
1620 }
1621 }
1622 }
1623 }
1624 else {
1625 return "";
1626 }
1627}
1628
1629sub synch_Cmd($)
1630{
1631 my $Name = $_[0];
1632 if(not $GCC_PATH)
1633 { # GCC was not found yet
1634 return "";
1635 }
1636 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001637 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001638 return $Candidate;
1639 }
1640 return "";
1641}
1642
1643sub get_CmdPath($)
1644{
1645 my $Name = $_[0];
1646 return "" if(not $Name);
1647 if(defined $Cache{"get_CmdPath"}{$Name}) {
1648 return $Cache{"get_CmdPath"}{$Name};
1649 }
1650 my %BinUtils = map {$_=>1} (
1651 "c++filt",
1652 "objdump",
1653 "readelf"
1654 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001655 if($BinUtils{$Name} and $GCC_PATH)
1656 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001657 if(my $Dir = get_dirname($GCC_PATH)) {
1658 $TargetTools{$Dir}=1;
1659 }
1660 }
1661 my $Path = search_Tools($Name);
1662 if(not $Path and $OSgroup eq "windows") {
1663 $Path = search_Tools($Name.".exe");
1664 }
1665 if(not $Path and $BinUtils{$Name})
1666 {
1667 if($CrossPrefix)
1668 { # user-defined prefix
1669 $Path = search_Cmd($CrossPrefix."-".$Name);
1670 }
1671 }
1672 if(not $Path and $BinUtils{$Name})
1673 {
1674 if(my $Candidate = synch_Cmd($Name))
1675 { # synch with GCC
1676 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001677 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001678 if(-f $Candidate) {
1679 $Path = $Candidate;
1680 }
1681 }
1682 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001683 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001684 $Path = $Candidate;
1685 }
1686 }
1687 }
1688 if(not $Path) {
1689 $Path = search_Cmd($Name);
1690 }
1691 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001692 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001693 $Path=search_Cmd($Name.".exe");
1694 }
1695 if($Path=~/\s/) {
1696 $Path = "\"".$Path."\"";
1697 }
1698 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1699}
1700
1701sub search_Cmd($)
1702{
1703 my $Name = $_[0];
1704 return "" if(not $Name);
1705 if(defined $Cache{"search_Cmd"}{$Name}) {
1706 return $Cache{"search_Cmd"}{$Name};
1707 }
1708 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1709 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1710 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001711 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001713 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001714 if(-f $CmdPath)
1715 {
1716 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001717 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001718 }
1719 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1720 }
1721 }
1722 return ($Cache{"search_Cmd"}{$Name} = "");
1723}
1724
1725sub get_CmdPath_Default($)
1726{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001727 return "" if(not $_[0]);
1728 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1729 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001730 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001731 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1732}
1733
1734sub get_CmdPath_Default_I($)
1735{ # search in PATH
1736 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001737 if($Name=~/find/)
1738 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001739 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001740 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001741 }
1742 }
1743 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001744 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001745 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001746 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001747 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001749 if($OSgroup eq "windows")
1750 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001751 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001752 return $Name;
1753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001754 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001755 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001756 {
1757 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001758 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001759 }
1760 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001761 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001762}
1763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001764sub classifyPath($)
1765{
1766 my $Path = $_[0];
1767 if($Path=~/[\*\[]/)
1768 { # wildcard
1769 $Path=~s/\*/.*/g;
1770 $Path=~s/\\/\\\\/g;
1771 return ($Path, "Pattern");
1772 }
1773 elsif($Path=~/[\/\\]/)
1774 { # directory or relative path
1775 return (path_format($Path, $OSgroup), "Path");
1776 }
1777 else {
1778 return ($Path, "Name");
1779 }
1780}
1781
1782sub readDescriptor($$)
1783{
1784 my ($LibVersion, $Content) = @_;
1785 return if(not $LibVersion);
1786 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1787 if(not $Content) {
1788 exitStatus("Error", "$DName is empty");
1789 }
1790 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001791 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001792 }
1793 $Content=~s/\/\*(.|\n)+?\*\///g;
1794 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001795
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1797 if($TargetVersion{$LibVersion}) {
1798 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1799 }
1800 if(not $Descriptor{$LibVersion}{"Version"}) {
1801 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1802 }
1803 if($Content=~/{RELPATH}/)
1804 {
1805 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1806 $Content =~ s/{RELPATH}/$RelDir/g;
1807 }
1808 else
1809 {
1810 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1811 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1812 }
1813 }
1814
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001815 my $DHeaders = parseTag(\$Content, "headers");
1816 if(not $DHeaders) {
1817 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1818 }
1819 elsif(lc($DHeaders) ne "none")
1820 { # append the descriptor headers list
1821 if($Descriptor{$LibVersion}{"Headers"})
1822 { # multiple descriptors
1823 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001825 else {
1826 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1827 }
1828 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1829 {
1830 if(not -e $Path) {
1831 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001832 }
1833 }
1834 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001835
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001836 if(not $CheckHeadersOnly_Opt)
1837 {
1838 my $DObjects = parseTag(\$Content, "libs");
1839 if(not $DObjects) {
1840 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1841 }
1842 elsif(lc($DObjects) ne "none")
1843 { # append the descriptor libraries list
1844 if($Descriptor{$LibVersion}{"Libs"})
1845 { # multiple descriptors
1846 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1847 }
1848 else {
1849 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1850 }
1851 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1852 {
1853 if(not -e $Path) {
1854 exitStatus("Access_Error", "can't access \'$Path\'");
1855 }
1856 }
1857 }
1858 }
1859 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1860 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001861 if(not -d $Path) {
1862 exitStatus("Access_Error", "can't access directory \'$Path\'");
1863 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001864 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001865 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001866 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001867 }
1868 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1869 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001870 if(not -d $Path) {
1871 exitStatus("Access_Error", "can't access directory \'$Path\'");
1872 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001873 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001874 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001875 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001876 }
1877 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1878 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 if(not -d $Path) {
1880 exitStatus("Access_Error", "can't access directory \'$Path\'");
1881 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001882 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001884 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 $TargetTools{$Path}=1;
1886 }
1887 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1888 $CrossPrefix = $Prefix;
1889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001890 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001891 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1892 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 if(not -d $Path) {
1894 exitStatus("Access_Error", "can't access directory \'$Path\'");
1895 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001896 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001898 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001899 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001900 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1902 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001903 if(not -d $Path) {
1904 exitStatus("Access_Error", "can't access directory \'$Path\'");
1905 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001906 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001907 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001908 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001909 }
1910 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001911 { # skip some auto-generated include paths
1912 if(not is_abs($Path))
1913 {
1914 if(my $P = abs_path($Path)) {
1915 $Path = $P;
1916 }
1917 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001918 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 }
1920 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001921 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 my ($CPath, $Type) = classifyPath($Path);
1923 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001924 }
1925 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001926 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1927 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001928 if($Option!~/\A\-(Wl|l|L)/)
1929 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001930 $CompilerOptions{$LibVersion} .= " ".$Option;
1931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001932 }
1933 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1934 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1935 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001936 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001937 my ($CPath, $Type) = classifyPath($Path);
1938 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001939 }
1940 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1941 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1942 {
1943 my ($CPath, $Type) = classifyPath($Path);
1944 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1945 }
1946 if(my $DDefines = parseTag(\$Content, "defines"))
1947 {
1948 if($Descriptor{$LibVersion}{"Defines"})
1949 { # multiple descriptors
1950 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1951 }
1952 else {
1953 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1954 }
1955 }
1956 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1957 {
1958 if($Order=~/\A(.+):(.+)\Z/) {
1959 $Include_Order{$LibVersion}{$1} = $2;
1960 }
1961 }
1962 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1963 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001964 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001965 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1966 }
1967 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1968 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001969 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001970 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1971 }
1972 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1973 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1974 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001975 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1976 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001978 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1979 $SkipConstants{$LibVersion}{$Constant} = 1;
1980 }
1981 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1982 {
1983 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001984 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001985 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1986 }
1987 else {
1988 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1989 }
1990 }
1991}
1992
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001993sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001994{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001995 my $CodeRef = shift(@_);
1996 my $Tag = shift(@_);
1997 if(not $Tag or not $CodeRef) {
1998 return undef;
1999 }
2000 my $Sp = 0;
2001 if(@_) {
2002 $Sp = shift(@_);
2003 }
2004 my $Start = index(${$CodeRef}, "<$Tag>");
2005 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002006 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002007 my $End = index(${$CodeRef}, "</$Tag>");
2008 if($End!=-1)
2009 {
2010 my $TS = length($Tag)+3;
2011 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2012 substr($Content, 0, $TS-1, ""); # cut start tag
2013 substr($Content, -$TS, $TS, ""); # cut end tag
2014 if(not $Sp)
2015 {
2016 $Content=~s/\A\s+//g;
2017 $Content=~s/\s+\Z//g;
2018 }
2019 if(substr($Content, 0, 1) ne "<") {
2020 $Content = xmlSpecChars_R($Content);
2021 }
2022 return $Content;
2023 }
2024 }
2025 return undef;
2026}
2027
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002028sub getInfo($)
2029{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002030 my $DumpPath = $_[0];
2031 return if(not $DumpPath or not -f $DumpPath);
2032
2033 readTUDump($DumpPath);
2034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 # processing info
2036 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002037
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002038 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002039 setAnonTypedef_All();
2040 }
2041
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002042 getTypeInfo_All();
2043 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002044 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002045 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002046 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002047
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002048 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002049 %LibInfo = ();
2050 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002051 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002052 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002053 %TemplateDecl = ();
2054 %StdCxxTypedef = ();
2055 %MissedTypedef = ();
2056 %Typedef_Tr = ();
2057 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002058 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002059
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002060 # clean cache
2061 delete($Cache{"getTypeAttr"});
2062 delete($Cache{"getTypeDeclId"});
2063
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002064 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002065 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002066 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002067 }
2068 else
2069 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002070 if($BinaryOnly and not $ExtendedCheck)
2071 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002072 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002073 }
2074 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002075 remove_Unused($Version, "Extended");
2076 }
2077 }
2078
2079 if($CheckInfo)
2080 {
2081 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2082 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2083 }
2084
2085 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2086 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002087 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002088 }
2089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002090 if($Debug) {
2091 # debugMangling($Version);
2092 }
2093}
2094
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002095sub readTUDump($)
2096{
2097 my $DumpPath = $_[0];
2098
2099 open(TU_DUMP, $DumpPath);
2100 local $/ = undef;
2101 my $Content = <TU_DUMP>;
2102 close(TU_DUMP);
2103
2104 unlink($DumpPath);
2105
2106 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002107 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002108
2109 # clean memory
2110 undef $Content;
2111
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002112 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113
2114 foreach (0 .. $#Lines)
2115 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002116 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002117 { # get a number and attributes of a node
2118 next if(not $NodeType{$2});
2119 $LibInfo{$Version}{"info_type"}{$1}=$2;
2120 $LibInfo{$Version}{"info"}{$1}=$3;
2121 }
2122
2123 # clean memory
2124 delete($Lines[$_]);
2125 }
2126
2127 # clean memory
2128 undef @Lines;
2129}
2130
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002131sub simplifyConstants()
2132{
2133 foreach my $Constant (keys(%{$Constants{$Version}}))
2134 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002135 if(defined $Constants{$Version}{$Constant}{"Header"})
2136 {
2137 my $Value = $Constants{$Version}{$Constant}{"Value"};
2138 if(defined $EnumConstants{$Version}{$Value}) {
2139 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2140 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002141 }
2142 }
2143}
2144
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002145sub simplifyNames()
2146{
2147 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2148 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002149 if($Typedef_Eq{$Version}{$Base}) {
2150 next;
2151 }
2152 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2153 if($#Translations==0)
2154 {
2155 if(length($Translations[0])<=length($Base)) {
2156 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2157 }
2158 }
2159 else
2160 { # select most appropriate
2161 foreach my $Tr (@Translations)
2162 {
2163 if($Base=~/\A\Q$Tr\E/)
2164 {
2165 $Typedef_Eq{$Version}{$Base} = $Tr;
2166 last;
2167 }
2168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002169 }
2170 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002171 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002172 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002173 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002174 if(not $TypeName) {
2175 next;
2176 }
2177 next if(index($TypeName,"<")==-1);# template instances only
2178 if($TypeName=~/>(::\w+)+\Z/)
2179 { # skip unused types
2180 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002181 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002182 foreach my $Base (sort {length($b)<=>length($a)}
2183 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002184 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002185 next if(not $Base);
2186 next if(index($TypeName,$Base)==-1);
2187 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002188 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002189 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002190 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2191 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2192 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002193 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002194 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2195 {
2196 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2197 {
2198 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2199 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002200 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002201 }
2202 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002205 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002206 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002207 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2208 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002209 }
2210}
2211
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002212sub setAnonTypedef_All()
2213{
2214 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2215 {
2216 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2217 {
2218 if(isAnon(getNameByInfo($InfoId))) {
2219 $TypedefToAnon{getTypeId($InfoId)} = 1;
2220 }
2221 }
2222 }
2223}
2224
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002225sub setTemplateParams_All()
2226{
2227 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2228 {
2229 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2230 setTemplateParams($_);
2231 }
2232 }
2233}
2234
2235sub setTemplateParams($)
2236{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002237 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002238 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002239 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002240 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002241 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002242 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002243 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002244 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002245 setTemplateInstParams($_[0], $TmplInst_Id);
2246 }
2247 }
2248
2249 $BasicTemplate{$Version}{$Tid} = $_[0];
2250
2251 if(my $Prms = getTreeAttr_Prms($_[0]))
2252 {
2253 if(my $Valu = getTreeAttr_Valu($Prms))
2254 {
2255 my $Vector = getTreeVec($Valu);
2256 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2257 {
2258 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2259 {
2260 if(my $Name = getNameByInfo($Val))
2261 {
2262 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2263 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2264 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2265 }
2266 else {
2267 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2268 }
2269 }
2270 }
2271 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002273 }
2274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002275 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002276 {
2277 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2278 {
2279 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002280 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002281 }
2282 }
2283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002284}
2285
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002286sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002287{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002288 my ($Tmpl, $Inst) = @_;
2289
2290 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002291 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002292 my ($Params_InfoId, $ElemId) = ();
2293 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2294 $Params_InfoId = $1;
2295 }
2296 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2297 $ElemId = $1;
2298 }
2299 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002300 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002301 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2302 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2303 {
2304 my ($PPos, $PTypeId) = ($1, $2);
2305 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2306 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002307 if($PType eq "template_type_parm") {
2308 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002309 }
2310 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002311 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2312 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002313 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002314 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002316 else
2317 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002318 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002319 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002321 }
2322 }
2323 }
2324}
2325
2326sub getTypeDeclId($)
2327{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002328 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002330 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2331 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2332 }
2333 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2334 {
2335 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2336 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2337 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002339 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002340 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341}
2342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002343sub getTypeInfo_All()
2344{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002345 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002346 { # support for GCC < 4.5
2347 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2348 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2349 # FIXME: check GCC versions
2350 addMissedTypes_Pre();
2351 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002353 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002354 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002355 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2356 if($IType=~/_type\Z/ and $IType ne "function_type"
2357 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002358 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002359 }
2360 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002361
2362 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002363 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002364 "Name" => "...",
2365 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002366 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002368 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002369
2370 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002371 { # support for GCC < 4.5
2372 addMissedTypes_Post();
2373 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002374
2375 if($ADD_TMPL_INSTANCES)
2376 {
2377 # templates
2378 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2379 {
2380 if(defined $TemplateMap{$Version}{$Tid}
2381 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2382 {
2383 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2384 {
2385 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2386 {
2387 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2388 {
2389 if(my %MAttr = getTypeAttr($MembTypeId))
2390 {
2391 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2392 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2393 }
2394 }
2395 }
2396 }
2397 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2398 {
2399 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2400 {
2401 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2402
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002403 if($NBid ne $Bid
2404 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002405 {
2406 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2407 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2408 }
2409 }
2410 }
2411 }
2412 }
2413 }
2414}
2415
2416sub createType($$)
2417{
2418 my ($Attr, $LibVersion) = @_;
2419 my $NewId = ++$MAX_ID;
2420
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002421 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002422 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002423 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002424
2425 return "$NewId";
2426}
2427
2428sub instType($$$)
2429{ # create template instances
2430 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002431
2432 if(not $TypeInfo{$LibVersion}{$Tid}) {
2433 return undef;
2434 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002435 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2436
2437 foreach my $Key (sort keys(%{$Map}))
2438 {
2439 if(my $Val = $Map->{$Key})
2440 {
2441 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2442
2443 if(defined $Attr->{"NameSpace"}) {
2444 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2445 }
2446 foreach (keys(%{$Attr->{"TParam"}})) {
2447 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2448 }
2449 }
2450 else
2451 { # remove absent
2452 # _Traits, etc.
2453 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002454 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002455 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2456 }
2457 foreach (keys(%{$Attr->{"TParam"}}))
2458 {
2459 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2460 delete($Attr->{"TParam"}{$_});
2461 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002462 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002463 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2464 }
2465 }
2466 }
2467 }
2468
2469 my $Tmpl = 0;
2470
2471 if(defined $Attr->{"TParam"})
2472 {
2473 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2474 {
2475 my $PName = $Attr->{"TParam"}{$_}{"name"};
2476
2477 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2478 {
2479 my %Base = get_BaseType($PTid, $LibVersion);
2480
2481 if($Base{"Type"} eq "TemplateParam"
2482 or defined $Base{"Template"})
2483 {
2484 $Tmpl = 1;
2485 last
2486 }
2487 }
2488 }
2489 }
2490
2491 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2492 return "$Id";
2493 }
2494 else
2495 {
2496 if(not $Tmpl) {
2497 delete($Attr->{"Template"});
2498 }
2499
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002500 my $New = createType($Attr, $LibVersion);
2501
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002502 my %EMap = ();
2503 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2504 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2505 }
2506 foreach (keys(%{$Map})) {
2507 $EMap{$_} = $Map->{$_};
2508 }
2509
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002510 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2511 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002512 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002513 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002514 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002515 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002516 {
2517 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2518
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002519 if($NBid ne $Bid
2520 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002521 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002522 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2523 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002524 }
2525 }
2526 }
2527
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002528 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002530 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2531 {
2532 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2533 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2534 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 }
2536 }
2537
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002538 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002539 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002540 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2541 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002542 }
2543 }
2544
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002545 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2546 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002547 }
2548
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002549 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002551}
2552
2553sub addMissedTypes_Pre()
2554{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002555 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002556 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2557 { # detecting missed typedefs
2558 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2559 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002560 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002561 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002562 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002563 if($TypeType eq "Unknown")
2564 { # template_type_parm
2565 next;
2566 }
2567 my $TypeDeclId = getTypeDeclId($TypeId);
2568 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2569 my $TypedefName = getNameByInfo($MissedTDid);
2570 next if(not $TypedefName);
2571 next if($TypedefName eq "__float80");
2572 next if(isAnon($TypedefName));
2573 if(not $TypeDeclId
2574 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002575 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002576 }
2577 }
2578 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002579 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002580 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002582 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002584 next;
2585 }
2586 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002587 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002588 if(not $TypedefName) {
2589 next;
2590 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002591 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 my %MissedInfo = ( # typedef info
2593 "Name" => $TypedefName,
2594 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002595 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002597 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002598 my ($H, $L) = getLocation($MissedTDid);
2599 $MissedInfo{"Header"} = $H;
2600 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002601 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002602 { # other types
2603 next;
2604 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002605 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002607 next;
2608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002609 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002611 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002613 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 next;
2616 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002617 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 next;
2619 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002620 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002621 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622 next;
2623 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002624 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 next;
2627 }
2628 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002629
2630 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002632 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002633 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002634 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002635 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002636 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002637
2638 # add missed & remove other
2639 $TypeInfo{$Version} = \%AddTypes;
2640 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641}
2642
2643sub addMissedTypes_Post()
2644{
2645 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2646 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002647 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2648 {
2649 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2650 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2651 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2652 }
2653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654 }
2655}
2656
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002657sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002658{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002659 my $TypeId = $_[0];
2660 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2661 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002662 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002663 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002665}
2666
2667sub getArraySize($$)
2668{
2669 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002670 if(my $Size = getSize($TypeId))
2671 {
2672 my $Elems = $Size/$BYTE_SIZE;
2673 while($BaseName=~s/\s*\[(\d+)\]//) {
2674 $Elems/=$1;
2675 }
2676 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2677 {
2678 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2679 $Elems/=$BasicSize;
2680 }
2681 }
2682 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002684 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002685}
2686
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002687sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002688{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002689 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002690 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002691 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2692 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002693 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002694 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2695 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2696 if(not $NodeType)
2697 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698 return ();
2699 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002700 if($NodeType eq "tree_vec")
2701 {
2702 if($Pos!=$#Positions)
2703 { # select last vector of parameters ( ns<P1>::type<P2> )
2704 next;
2705 }
2706 }
2707 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2708 foreach my $P (@Params)
2709 {
2710 if($P eq "") {
2711 return ();
2712 }
2713 elsif($P ne "\@skip\@") {
2714 @TmplParams = (@TmplParams, $P);
2715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 }
2717 }
2718 return @TmplParams;
2719}
2720
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002721sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002723 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002724 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002725 if(defined $TypeInfo{$Version}{$TypeId}
2726 and $TypeInfo{$Version}{$TypeId}{"Name"})
2727 { # already created
2728 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002729 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002730 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2731 { # incomplete type
2732 return ();
2733 }
2734 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2735
2736 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738
2739 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2740 {
2741 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2742 {
2743 if($Info=~/qual[ ]*:/)
2744 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002745 my $NewId = ++$MAX_ID;
2746
2747 $MissedBase{$Version}{$TypeId} = "$NewId";
2748 $MissedBase_R{$Version}{$NewId} = $TypeId;
2749 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2750 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002751 }
2752 }
2753 $TypeAttr{"Type"} = "Typedef";
2754 }
2755 else {
2756 $TypeAttr{"Type"} = getTypeType($TypeId);
2757 }
2758
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002759 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2760 {
2761 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2762 { # local code
2763 return ();
2764 }
2765 }
2766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 if($TypeAttr{"Type"} eq "Unknown") {
2768 return ();
2769 }
2770 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002772 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002773 if(my $TName = $TypeAttr{"Name"})
2774 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002776 $TName_Tid{$Version}{$TName} = $TypeId;
2777 return %TypeAttr;
2778 }
2779 else {
2780 return ();
2781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002782 }
2783 elsif($TypeAttr{"Type"} eq "Array")
2784 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002785 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2786 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002787 return ();
2788 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002789 if(my $Algn = getAlgn($TypeId)) {
2790 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002792 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002793 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002794 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002795 if(not $BTAttr{"Name"}) {
2796 return ();
2797 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002798 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002800 if(my $Size = getSize($TypeId)) {
2801 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2802 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002803 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002804 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2805 }
2806 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002807 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002809 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002810 else
2811 {
2812 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002813 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002814 $TypeAttr{"Name"} = $1."[]".$2;
2815 }
2816 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002817 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002819 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002820 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 if($BTAttr{"Header"}) {
2822 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002823 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002824 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002825 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2826 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002828 return ();
2829 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002830 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002831 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002832 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002833 if($TypeAttr{"Name"})
2834 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002835 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002836
2837 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2838 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002839 { # NOTE: register only one int: with built-in decl
2840 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2841 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2842 }
2843 }
2844 return %TypeAttr;
2845 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002846 else {
2847 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002849 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002850 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2851 {
2852 %TypeAttr = getTrivialTypeAttr($TypeId);
2853 if($TypeAttr{"Name"})
2854 {
2855 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2856 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2857 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2858 }
2859 return %TypeAttr;
2860 }
2861 else {
2862 return ();
2863 }
2864 }
2865 elsif($TypeAttr{"Type"} eq "SizeOf")
2866 {
2867 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2868 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2869 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2870 if($TypeAttr{"Name"})
2871 {
2872 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2873 return %TypeAttr;
2874 }
2875 else {
2876 return ();
2877 }
2878 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002879 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002880 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002881 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2882 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002883 return ();
2884 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002885 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002887 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002888 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002889 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002890 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002891 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 }
2894 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002895 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002896 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002897 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002898 return ();
2899 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002900 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002901 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002902 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002903 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002904 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002905 }
2906 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002907 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002908 {
2909 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002910 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002911 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002912 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002913 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2914 }
2915 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002916 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002917 }
2918 }
2919 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002920 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002921 }
2922 if($TypeAttr{"Type"} eq "Typedef")
2923 {
2924 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002925
2926 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2927 return ();
2928 }
2929
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002930 if(isAnon($TypeAttr{"Name"}))
2931 { # anon typedef to anon type: ._N
2932 return ();
2933 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002934
2935 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2936 { # artificial typedef of "struct X" to "X"
2937 $TypeAttr{"Artificial"} = 1;
2938 }
2939
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002940 if(my $NS = getNameSpace($TypeDeclId))
2941 {
2942 my $TypeName = $TypeAttr{"Name"};
2943 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2944 { # "some_type" is the typedef to "struct some_type" in C++
2945 if($3) {
2946 $TypeAttr{"Name"} = $3."::".$TypeName;
2947 }
2948 }
2949 else
2950 {
2951 $TypeAttr{"NameSpace"} = $NS;
2952 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002953
2954 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2955 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2956 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002957 if($BTAttr{"NameSpace"}
2958 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002959 { # types like "std::fpos<__mbstate_t>" are
2960 # not covered by typedefs in the TU dump
2961 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002962 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2963 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002964 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002966 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002967 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002969 }
2970 }
2971 }
2972 }
2973 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002974 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002975 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002976 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002977 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2978 { # typedef int*const TYPEDEF; // first
2979 # int foo(TYPEDEF p); // const is optimized out
2980 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2981 if($BTAttr{"Name"}=~/</)
2982 {
2983 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2984 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002986 }
2987 }
2988 }
2989 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2990 }
2991 if(not $TypeAttr{"Size"})
2992 {
2993 if($TypeAttr{"Type"} eq "Pointer") {
2994 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2995 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002996 elsif($BTAttr{"Size"}) {
2997 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002998 }
2999 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003000 if(my $Algn = getAlgn($TypeId)) {
3001 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3002 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003003 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003004 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3005 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003006 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003007 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003008 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003009 { # typedef to "class Class"
3010 # should not be registered in TName_Tid
3011 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3012 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003014 }
3015 return %TypeAttr;
3016 }
3017}
3018
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003019sub getTreeVec($)
3020{
3021 my %Vector = ();
3022 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3023 {
3024 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3025 { # string length is N-1 because of the null terminator
3026 $Vector{$1} = $2;
3027 }
3028 }
3029 return \%Vector;
3030}
3031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003032sub get_TemplateParam($$)
3033{
3034 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003035 return () if(not $Type_Id);
3036 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3037 return () if(not $NodeType);
3038 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003039 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003040 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003041 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 my $Num = getNodeIntCst($Type_Id);
3043 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003044 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003045 }
3046 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003047 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003048 }
3049 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003050 elsif($NodeType eq "string_cst") {
3051 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003053 elsif($NodeType eq "tree_vec")
3054 {
3055 my $Vector = getTreeVec($Type_Id);
3056 my @Params = ();
3057 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3058 {
3059 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3060 push(@Params, $P2);
3061 }
3062 }
3063 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003064 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003065 elsif($NodeType eq "parm_decl")
3066 {
3067 (getNameByInfo($Type_Id));
3068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 else
3070 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003071 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003072 my $PName = $ParamAttr{"Name"};
3073 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003074 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003075 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003076 if($PName=~/\>/)
3077 {
3078 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003079 $PName = $Cover;
3080 }
3081 }
3082 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003083 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003084 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3085 # template<typename _Key, typename _Compare = std::less<_Key>
3086 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3087 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3088 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3089 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003090 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003091 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003092 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 }
3094}
3095
3096sub cover_stdcxx_typedef($)
3097{
3098 my $TypeName = $_[0];
3099 if(my @Covers = sort {length($a)<=>length($b)}
3100 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3101 { # take the shortest typedef
3102 # FIXME: there may be more than
3103 # one typedefs to the same type
3104 return $Covers[0];
3105 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003106 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003107 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3108 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3109 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003110 if(my $Cover = $Covers[0])
3111 {
3112 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3113 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003115 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003116 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003117}
3118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119sub getNodeIntCst($)
3120{
3121 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003122 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 if($EnumMembName_Id{$Version}{$CstId}) {
3124 return $EnumMembName_Id{$Version}{$CstId};
3125 }
3126 elsif((my $Value = getTreeValue($CstId)) ne "")
3127 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003128 if($Value eq "0")
3129 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003130 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003131 return "false";
3132 }
3133 else {
3134 return "0";
3135 }
3136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003137 elsif($Value eq "1")
3138 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003139 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003140 return "true";
3141 }
3142 else {
3143 return "1";
3144 }
3145 }
3146 else {
3147 return $Value;
3148 }
3149 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003150 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003151}
3152
3153sub getNodeStrCst($)
3154{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003155 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3156 {
3157 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003158 {
3159 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3160 { # string length is N-1 because of the null terminator
3161 return substr($1, 0, $2-1);
3162 }
3163 else
3164 { # identifier_node
3165 return substr($1, 0, $2);
3166 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003169 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003170}
3171
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003172sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003174 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003175 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3176 if($Type eq "FieldPtr") {
3177 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3178 }
3179 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3180 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003181 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003182 if($Type eq "MethodPtr")
3183 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003184 if(my $Size = getSize($TypeId))
3185 {
3186 $Size/=$BYTE_SIZE;
3187 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003189 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003190 if(my $Algn = getAlgn($TypeId)) {
3191 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003193 # Return
3194 if($Type eq "FieldPtr")
3195 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003196 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003197 if($ReturnAttr{"Name"}) {
3198 $MemPtrName .= $ReturnAttr{"Name"};
3199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003200 $TypeAttr{"Return"} = $PtrId;
3201 }
3202 else
3203 {
3204 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3205 {
3206 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003207 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3208 if(not $ReturnAttr{"Name"})
3209 { # templates
3210 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003211 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003212 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003213 $TypeAttr{"Return"} = $ReturnTypeId;
3214 }
3215 }
3216 # Class
3217 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3218 {
3219 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003220 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003221 if($Class{"Name"}) {
3222 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3223 }
3224 else {
3225 $MemPtrName .= " (*)";
3226 }
3227 }
3228 else {
3229 $MemPtrName .= " (*)";
3230 }
3231 # Parameters
3232 if($Type eq "FuncPtr"
3233 or $Type eq "MethodPtr")
3234 {
3235 my @ParamTypeName = ();
3236 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3237 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003238 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003239 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003240 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003242 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3243 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003244 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003245 my $PTypeId = $1;
3246 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003247 if(not $ParamAttr{"Name"})
3248 { # templates (template_type_parm), etc.
3249 return ();
3250 }
3251 if($ParamAttr{"Name"} eq "void") {
3252 last;
3253 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003254 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003255 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003256 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003257 push(@ParamTypeName, $ParamAttr{"Name"});
3258 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003259 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3260 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003261 }
3262 else {
3263 last;
3264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003265 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003266 else {
3267 last;
3268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003269 }
3270 }
3271 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3272 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003273 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 return %TypeAttr;
3275}
3276
3277sub getTreeTypeName($)
3278{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003279 my $TypeId = $_[0];
3280 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003281 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003282 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003283 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003284 if(my $Name = getNameByInfo($TypeId))
3285 { # bit_size_type
3286 return $Name;
3287 }
3288 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003289 return "unsigned int";
3290 }
3291 else {
3292 return "int";
3293 }
3294 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003295 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003296 return getNameByInfo($1);
3297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003299 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003300}
3301
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003302sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003303{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003304 my $Ptd = pointTo($_[0]);
3305 return 0 if(not $Ptd);
3306 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003307 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003308 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3309 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003310 }
3311 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003312 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3313 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003314 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003315 if($InfoT1 eq "pointer_type"
3316 and $InfoT2 eq "function_type") {
3317 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318 }
3319 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003320 return 0;
3321}
3322
3323sub isMethodPtr($)
3324{
3325 my $Ptd = pointTo($_[0]);
3326 return 0 if(not $Ptd);
3327 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3328 {
3329 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3330 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3331 and $Info=~/ ptrmem /) {
3332 return 1;
3333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003334 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003335 return 0;
3336}
3337
3338sub isFieldPtr($)
3339{
3340 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3341 {
3342 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3343 and $Info=~/ ptrmem /) {
3344 return 1;
3345 }
3346 }
3347 return 0;
3348}
3349
3350sub pointTo($)
3351{
3352 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3353 {
3354 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3355 return $1;
3356 }
3357 }
3358 return "";
3359}
3360
3361sub getTypeTypeByTypeId($)
3362{
3363 my $TypeId = $_[0];
3364 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3365 {
3366 my $NType = $NodeType{$TType};
3367 if($NType eq "Intrinsic") {
3368 return $NType;
3369 }
3370 elsif(isFuncPtr($TypeId)) {
3371 return "FuncPtr";
3372 }
3373 elsif(isMethodPtr($TypeId)) {
3374 return "MethodPtr";
3375 }
3376 elsif(isFieldPtr($TypeId)) {
3377 return "FieldPtr";
3378 }
3379 elsif($NType ne "Other") {
3380 return $NType;
3381 }
3382 }
3383 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003384}
3385
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003386my %UnQual = (
3387 "r"=>"restrict",
3388 "v"=>"volatile",
3389 "c"=>"const",
3390 "cv"=>"const volatile"
3391);
3392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003393sub getQual($)
3394{
3395 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003396 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3397 {
3398 my ($Qual, $To) = ();
3399 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3400 $Qual = $UnQual{$1};
3401 }
3402 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3403 $To = $1;
3404 }
3405 if($Qual and $To) {
3406 return ($Qual, $To);
3407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003408 }
3409 return ();
3410}
3411
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003412sub getQualType($)
3413{
3414 if($_[0] eq "const volatile") {
3415 return "ConstVolatile";
3416 }
3417 return ucfirst($_[0]);
3418}
3419
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003420sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003421{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003422 my $TypeId = $_[0];
3423 my $TypeDeclId = getTypeDeclId($TypeId);
3424 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003425 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003426 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3427 return "Typedef";
3428 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003429 }
3430 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3431 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003432 if(($Qual or $To) and $TypeDeclId
3433 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003434 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003435 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003437 elsif(not $MissedBase_R{$Version}{$TypeId}
3438 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439 return "Typedef";
3440 }
3441 elsif($Qual)
3442 { # qualified types
3443 return getQualType($Qual);
3444 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003445
3446 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3447 { # typedef struct { ... } name
3448 $TypeTypedef{$Version}{$TypeId} = $1;
3449 }
3450
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003451 my $TypeType = getTypeTypeByTypeId($TypeId);
3452 if($TypeType eq "Struct")
3453 {
3454 if($TypeDeclId
3455 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3456 return "Template";
3457 }
3458 }
3459 return $TypeType;
3460}
3461
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003462sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003463{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003464 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003465 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003466 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3467 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3468 return 0;
3469 }
3470 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3471 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003472 if(my $TDid = getTypeDeclId($_[0]))
3473 {
3474 if(getTypeId($TDid) eq $_[0]
3475 and getNameByInfo($TDid))
3476 {
3477 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3478 return $1;
3479 }
3480 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003482 }
3483 }
3484 return 0;
3485}
3486
3487sub selectBaseType($)
3488{
3489 my $TypeId = $_[0];
3490 if(defined $MissedTypedef{$Version}{$TypeId})
3491 { # add missed typedefs
3492 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3493 return ($TypeId, "");
3494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003495 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003496 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3497 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003498
3499 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3500 my $MB = $MissedBase{$Version}{$TypeId};
3501
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003502 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003503 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003504 and (getTypeId($1) ne $TypeId)
3505 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003506 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003507 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003508 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 elsif($MB)
3510 { # add base
3511 return ($MB, "");
3512 }
3513 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003514 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003517 elsif($Qual or $To)
3518 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003519 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003520 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003521 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003524 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003527 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003529 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003530 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003532 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003533 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003535 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003536 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003538 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003539
3540 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541}
3542
3543sub getSymbolInfo_All()
3544{
3545 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3546 { # reverse order
3547 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003548 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 }
3550 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003551
3552 if($ADD_TMPL_INSTANCES)
3553 {
3554 # templates
3555 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3556 {
3557 my %Map = ();
3558
3559 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3560 {
3561 if(defined $TemplateMap{$Version}{$ClassId})
3562 {
3563 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3564 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3565 }
3566 }
3567 }
3568
3569 if(defined $TemplateMap{$Version}{$Sid})
3570 {
3571 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3572 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3573 }
3574 }
3575
3576 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3577 {
3578 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3579 {
3580 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3581 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3582 }
3583 }
3584 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3585 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3586 }
3587 }
3588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003589}
3590
3591sub getVarInfo_All()
3592{
3593 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3594 { # reverse order
3595 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003596 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003597 }
3598 }
3599}
3600
3601sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003602 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003603}
3604
3605sub getVarInfo($)
3606{
3607 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003608 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003609 {
3610 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3611 if($NSInfoType and $NSInfoType eq "function_decl") {
3612 return;
3613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003614 }
3615 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3616 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3617 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3618 delete($SymbolInfo{$Version}{$InfoId});
3619 return;
3620 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003621 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003622 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003623 delete($SymbolInfo{$Version}{$InfoId});
3624 return;
3625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003626 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3627 delete($SymbolInfo{$Version}{$InfoId});
3628 return;
3629 }
3630 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003631 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3632 {
3633 if($OSgroup eq "windows")
3634 { # cut the offset
3635 $MnglName=~s/\@\d+\Z//g;
3636 }
3637 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003639 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003640 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003641 { # validate mangled name
3642 delete($SymbolInfo{$Version}{$InfoId});
3643 return;
3644 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003645 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003646 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003647 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003648 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003649 }
3650 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3651 { # non-public global data
3652 delete($SymbolInfo{$Version}{$InfoId});
3653 return;
3654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003655 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003656 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003657 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003658 if(not defined $TypeInfo{$Version}{$Rid}
3659 or not $TypeInfo{$Version}{$Rid}{"Name"})
3660 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003661 delete($SymbolInfo{$Version}{$InfoId});
3662 return;
3663 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3665 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003666 if(defined $Val) {
3667 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003669 }
3670 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003671 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3672 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003673 if(not defined $TypeInfo{$Version}{$ClassId}
3674 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3675 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 delete($SymbolInfo{$Version}{$InfoId});
3677 return;
3678 }
3679 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003680 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3681 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003683 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003684 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003685 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003686 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003687 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003688 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003689 if(not $CheckHeadersOnly)
3690 {
3691 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3692 {
3693 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3694 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3695 {
3696 if(link_symbol($ShortName, $Version, "-Deps"))
3697 { # "const" global data is mangled as _ZL... in the TU dump
3698 # but not mangled when compiling a C shared library
3699 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3700 }
3701 }
3702 }
3703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003704 if($COMMON_LANGUAGE{$Version} eq "C++")
3705 {
3706 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3707 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003708 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3710 }
3711 }
3712 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3713 { # try to mangle symbol (link with libraries)
3714 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3715 }
3716 if($OStarget eq "windows")
3717 {
3718 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3719 { # link MS C++ symbols from library with GCC symbols from headers
3720 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3721 }
3722 }
3723 }
3724 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3725 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3726 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003727 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3728 {
3729 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3730 { # non-target symbols
3731 delete($SymbolInfo{$Version}{$InfoId});
3732 return;
3733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003735 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3736 {
3737 if(defined $MissedTypedef{$Version}{$Rid})
3738 {
3739 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3740 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3741 }
3742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003743 }
3744 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003745 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003746 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3747 }
3748 if($ShortName=~/\A(_Z|\?)/) {
3749 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3750 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003751
3752 if($ExtraDump) {
3753 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003755}
3756
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003757sub isConstType($$)
3758{
3759 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003760 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003761 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003762 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003763 }
3764 return ($Base{"Type"} eq "Const");
3765}
3766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003767sub getTrivialName($$)
3768{
3769 my ($TypeInfoId, $TypeId) = @_;
3770 my %TypeAttr = ();
3771 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3772 if(not $TypeAttr{"Name"}) {
3773 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3774 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003775 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003776 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003777 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003778 if(isAnon($TypeAttr{"Name"}))
3779 {
3780 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003781 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003782 { # searching for a first not anon scope
3783 if($NSId eq $NameSpaceId) {
3784 last;
3785 }
3786 else
3787 {
3788 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3789 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003790 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003791 last;
3792 }
3793 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003794 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003795 }
3796 }
3797 else
3798 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003799 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003800 {
3801 if($NameSpaceId ne $TypeId) {
3802 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003804 }
3805 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003806 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003807 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3808 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003809 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003810 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003811 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003812 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003813 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003814 if($TypeAttr{"NameSpace"}) {
3815 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003818 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3819 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003820 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003821 if(my @TParams = getTParams($TypeId, "Type")) {
3822 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3823 }
3824 else {
3825 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003827 }
3828 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3829}
3830
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003831sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003832{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003833 my $TypeId = $_[0];
3834 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003835
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003836 my %TypeAttr = ();
3837
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003838 if($TemplateDecl{$Version}{$TypeId})
3839 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003840 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003841 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003842
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003843 setTypeAccess($TypeId, \%TypeAttr);
3844 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3845 if(isBuiltIn($TypeAttr{"Header"}))
3846 {
3847 delete($TypeAttr{"Header"});
3848 delete($TypeAttr{"Line"});
3849 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003850
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003851 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003852 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3853 if(not $TypeAttr{"Name"}) {
3854 return ();
3855 }
3856 if(not $TypeAttr{"NameSpace"}) {
3857 delete($TypeAttr{"NameSpace"});
3858 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003859
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003860 if($TypeAttr{"Type"} eq "Intrinsic")
3861 {
3862 if(defined $TypeAttr{"Header"})
3863 {
3864 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3865 { # support for SUSE 11.2
3866 # integer_type has srcp dump{1-2}.i
3867 delete($TypeAttr{"Header"});
3868 }
3869 }
3870 }
3871
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003872 my $Tmpl = undef;
3873
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003874 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003875 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003876 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3877
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003878 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003879 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003880 foreach my $Pos (0 .. $#TParams)
3881 {
3882 my $Val = $TParams[$Pos];
3883 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3884
3885 if(not defined $TypeAttr{"Template"})
3886 {
3887 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3888
3889 if($Base{"Type"} eq "TemplateParam"
3890 or defined $Base{"Template"}) {
3891 $TypeAttr{"Template"} = 1;
3892 }
3893 }
3894
3895 if($Tmpl)
3896 {
3897 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3898 {
3899 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3900
3901 if($Val eq $Arg) {
3902 $TypeAttr{"Template"} = 1;
3903 }
3904 }
3905 }
3906 }
3907
3908 if($Tmpl)
3909 {
3910 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3911 {
3912 if($Pos>$#TParams)
3913 {
3914 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3915 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3916 }
3917 }
3918 }
3919 }
3920
3921 if($ADD_TMPL_INSTANCES)
3922 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003923 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003924 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003925 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003926 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003927 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003928 {
3929 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3930 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3931 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003932 }
3933 if(not getTreeAttr_Binf($TypeId))
3934 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003935 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3936 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3937 }
3938 }
3939 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003940 }
3941 }
3942 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003943
3944 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3945
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003946 if(my $Size = getSize($TypeId))
3947 {
3948 $Size = $Size/$BYTE_SIZE;
3949 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003950 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003951 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003952 {
3953 if($ExtraDump)
3954 {
3955 if(not defined $TypeAttr{"Memb"}
3956 and not $Tmpl)
3957 { # declaration only
3958 $TypeAttr{"Forward"} = 1;
3959 }
3960 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003961 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003963 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003964 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003965 {
3966 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003967 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003968 }
3969 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003970 or $TypeAttr{"Type"} eq "Class")
3971 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003972 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003973 if($Skip) {
3974 return ();
3975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003976 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003977 if(my $Algn = getAlgn($TypeId)) {
3978 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003980 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003981
3982 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3983 {
3984 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003985 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003986 {
3987 if(not isAnon($TypeAttr{"Name"})) {
3988 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3989 }
3990 }
3991 }
3992
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003993 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003994 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3995 {
3996 my @Entries = split(/\n/, $VTable);
3997 foreach (1 .. $#Entries)
3998 {
3999 my $Entry = $Entries[$_];
4000 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004001 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004002 }
4003 }
4004 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004005
4006 if($TypeAttr{"Type"} eq "Enum")
4007 {
4008 if(not $TypeAttr{"NameSpace"})
4009 {
4010 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4011 {
4012 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004013 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004014 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004015 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004016 "Header"=>$TypeAttr{"Header"}
4017 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004018 if(isAnon($TypeAttr{"Name"}))
4019 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004020 if($ExtraDump
4021 or is_target_header($TypeAttr{"Header"}, $Version))
4022 {
4023 %{$Constants{$Version}{$MName}} = (
4024 "Value" => $MVal,
4025 "Header" => $TypeAttr{"Header"}
4026 );
4027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004028 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004029 }
4030 }
4031 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004032 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004033 {
4034 if(defined $TypedefToAnon{$TypeId}) {
4035 $TypeAttr{"AnonTypedef"} = 1;
4036 }
4037 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004039 return %TypeAttr;
4040}
4041
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004042sub simplifyVTable($)
4043{
4044 my $Content = $_[0];
4045 if($Content=~s/ \[with (.+)]//)
4046 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4047 if(my @Elems = separate_Params($1, 0, 0))
4048 {
4049 foreach my $Elem (@Elems)
4050 {
4051 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4052 {
4053 my ($Arg, $Val) = ($1, $2);
4054
4055 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4056 $Content=~s/,\s*$Arg\b//g;
4057 }
4058 else {
4059 $Content=~s/\b$Arg\b/$Val/g;
4060 }
4061 }
4062 }
4063 }
4064 }
4065
4066 return $Content;
4067}
4068
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004069sub detect_lang($)
4070{
4071 my $TypeId = $_[0];
4072 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004073 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004074 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004075 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4076 }
4077 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004078 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004079 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004080 while($Fncs)
4081 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004082 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004083 return 1;
4084 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004085 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004086 }
4087 }
4088 return 0;
4089}
4090
4091sub setSpec($$)
4092{
4093 my ($TypeId, $TypeAttr) = @_;
4094 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4095 if($Info=~/\s+spec\s+/) {
4096 $TypeAttr->{"Spec"} = 1;
4097 }
4098}
4099
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004100sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004101{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004102 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004103 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004104 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004105 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004106 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004107 my $Pos = 0;
4108 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4109 {
4110 my ($Access, $BInfoId) = ($1, $2);
4111 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004112
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004113 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004114 { # class A<N>:public A<N-1>
4115 next;
4116 }
4117
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004118 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4119 if(not $CType or $CType eq "template_type_parm"
4120 or $CType eq "typename_type")
4121 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004122 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004124 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004125 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004126 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4127 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004128 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4130 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004131 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004132 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004133 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4135 }
4136 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004137 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004138 }
4139 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004140 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004141}
4142
4143sub getBinfClassId($)
4144{
4145 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4146 $Info=~/type[ ]*:[ ]*@(\d+) /;
4147 return $1;
4148}
4149
4150sub unmangledFormat($$)
4151{
4152 my ($Name, $LibVersion) = @_;
4153 $Name = uncover_typedefs($Name, $LibVersion);
4154 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4155 $Name=~s/\(\w+\)(\d)/$1/;
4156 return $Name;
4157}
4158
4159sub modelUnmangled($$)
4160{
4161 my ($InfoId, $Compiler) = @_;
4162 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4163 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4164 }
4165 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4166 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4167 $PureSignature = "~".$PureSignature;
4168 }
4169 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4170 {
4171 my (@Params, @ParamTypes) = ();
4172 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4173 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4174 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4175 }
4176 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4177 { # checking parameters
4178 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004179 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004180 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004181 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004182
4183 if($PName eq "this"
4184 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4185 {
4186 next;
4187 }
4188
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004189 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004190 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004191 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 }
4193 @ParamTypes = (@ParamTypes, $PTName);
4194 }
4195 if(@ParamTypes) {
4196 $PureSignature .= "(".join(", ", @ParamTypes).")";
4197 }
4198 else
4199 {
4200 if($Compiler eq "MSVC")
4201 {
4202 $PureSignature .= "(void)";
4203 }
4204 else
4205 { # GCC
4206 $PureSignature .= "()";
4207 }
4208 }
4209 $PureSignature = delete_keywords($PureSignature);
4210 }
4211 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4212 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004213 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004214 $PureSignature = $ClassName."::".$PureSignature;
4215 }
4216 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4217 $PureSignature = $NS."::".$PureSignature;
4218 }
4219 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4220 $PureSignature .= " const";
4221 }
4222 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4223 $PureSignature .= " volatile";
4224 }
4225 my $ShowReturn = 0;
4226 if($Compiler eq "MSVC"
4227 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4228 {
4229 $ShowReturn=1;
4230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004231 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4232 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004233 {
4234 $ShowReturn=1;
4235 }
4236 if($ShowReturn)
4237 { # mangled names for template function specializations include return value
4238 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4239 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004240 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004241 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4242 $PureSignature = $ReturnName." ".$PureSignature;
4243 }
4244 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004245 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004246}
4247
4248sub mangle_symbol($$$)
4249{ # mangling for simple methods
4250 # see gcc-4.6.0/gcc/cp/mangle.c
4251 my ($InfoId, $LibVersion, $Compiler) = @_;
4252 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4253 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4254 }
4255 my $Mangled = "";
4256 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004257 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004258 }
4259 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004260 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 }
4262 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4263}
4264
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004265sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004266{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004267 my ($InfoId, $LibVersion) = @_;
4268 return "";
4269}
4270
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004271sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004272{ # see gcc-4.6.0/gcc/cp/mangle.c
4273 my ($InfoId, $LibVersion) = @_;
4274 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004275 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004276 my %Repl = ();# SN_ replacements
4277 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4278 {
4279 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4280 if($MangledClass!~/\AN/) {
4281 $MangledClass = "N".$MangledClass;
4282 }
4283 else {
4284 $MangledClass=~s/E\Z//;
4285 }
4286 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4287 $MangledClass=~s/\AN/NV/;
4288 }
4289 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4290 $MangledClass=~s/\AN/NK/;
4291 }
4292 $Mangled .= $MangledClass;
4293 }
4294 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4295 { # mangled by name due to the absence of structured info
4296 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4297 if($MangledNS!~/\AN/) {
4298 $MangledNS = "N".$MangledNS;
4299 }
4300 else {
4301 $MangledNS=~s/E\Z//;
4302 }
4303 $Mangled .= $MangledNS;
4304 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004305 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004306 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004307 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004308 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004309 foreach (@TPos) {
4310 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4311 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004312 }
4313 elsif($TmplParams)
4314 { # remangling mode
4315 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004316 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004317 }
4318 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4319 $Mangled .= "C1";
4320 }
4321 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4322 $Mangled .= "D0";
4323 }
4324 elsif($ShortName)
4325 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004326 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4327 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004328 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004329 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004330 { # "const" global data is mangled as _ZL...
4331 $Mangled .= "L";
4332 }
4333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004334 if($ShortName=~/\Aoperator(\W.*)\Z/)
4335 {
4336 my $Op = $1;
4337 $Op=~s/\A[ ]+//g;
4338 if(my $OpMngl = $OperatorMangling{$Op}) {
4339 $Mangled .= $OpMngl;
4340 }
4341 else { # conversion operator
4342 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4343 }
4344 }
4345 else {
4346 $Mangled .= length($ShortName).$ShortName;
4347 }
4348 if(@TParams)
4349 { # templates
4350 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004351 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004352 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4353 }
4354 $Mangled .= "E";
4355 }
4356 if(not $ClassId and @TParams) {
4357 add_substitution($ShortName, \%Repl, 0);
4358 }
4359 }
4360 if($ClassId or $NameSpace) {
4361 $Mangled .= "E";
4362 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004363 if(@TParams)
4364 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004365 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004366 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4367 }
4368 }
4369 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4370 {
4371 my @Params = ();
4372 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4373 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4374 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4375 }
4376 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4377 { # checking parameters
4378 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4379 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4380 }
4381 if(not @Params) {
4382 $Mangled .= "v";
4383 }
4384 }
4385 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4386 $Mangled = write_stdcxx_substitution($Mangled);
4387 if($Mangled eq "_Z") {
4388 return "";
4389 }
4390 return $Mangled;
4391}
4392
4393sub correct_incharge($$$)
4394{
4395 my ($InfoId, $LibVersion, $Mangled) = @_;
4396 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4397 {
4398 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004399 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004400 }
4401 }
4402 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4403 {
4404 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004405 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004406 }
4407 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004408 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 }
4410 }
4411 return $Mangled;
4412}
4413
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004414sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004415{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004416 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004417 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004418 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004419 return $Name;
4420 }
4421 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004422 while(my $CPos = find_center($TParams, "<"))
4423 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004424 $TParams = substr($TParams, $CPos);
4425 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004426 if($TParams=~s/\A<(.+)>\Z/$1/) {
4427 $Name=~s/<\Q$TParams\E>\Z//;
4428 }
4429 else
4430 { # error
4431 $TParams = "";
4432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433 return ($Name, $TParams);
4434}
4435
4436sub get_sub_ns($)
4437{
4438 my $Name = $_[0];
4439 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004440 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004441 {
4442 push(@NS, substr($Name, 0, $CPos));
4443 $Name = substr($Name, $CPos);
4444 $Name=~s/\A:://;
4445 }
4446 return (join("::", @NS), $Name);
4447}
4448
4449sub mangle_ns($$$)
4450{
4451 my ($Name, $LibVersion, $Repl) = @_;
4452 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4453 {
4454 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4455 $Mangled=~s/\AN(.+)E\Z/$1/;
4456 return $Mangled;
4457
4458 }
4459 else
4460 {
4461 my ($MangledNS, $SubNS) = ("", "");
4462 ($SubNS, $Name) = get_sub_ns($Name);
4463 if($SubNS) {
4464 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4465 }
4466 $MangledNS .= length($Name).$Name;
4467 add_substitution($MangledNS, $Repl, 0);
4468 return $MangledNS;
4469 }
4470}
4471
4472sub mangle_param($$$)
4473{
4474 my ($PTid, $LibVersion, $Repl) = @_;
4475 my ($MPrefix, $Mangled) = ("", "");
4476 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004477 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004478 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004479 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004480 if(not $BaseType_Name) {
4481 return "";
4482 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004483 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004484 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004485 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4486 while($Suffix=~/(&|\*|const)\Z/)
4487 {
4488 if($Suffix=~s/[ ]*&\Z//) {
4489 $MPrefix .= "R";
4490 }
4491 if($Suffix=~s/[ ]*\*\Z//) {
4492 $MPrefix .= "P";
4493 }
4494 if($Suffix=~s/[ ]*const\Z//)
4495 {
4496 if($MPrefix=~/R|P/
4497 or $Suffix=~/&|\*/) {
4498 $MPrefix .= "K";
4499 }
4500 }
4501 if($Suffix=~s/[ ]*volatile\Z//) {
4502 $MPrefix .= "V";
4503 }
4504 #if($Suffix=~s/[ ]*restrict\Z//) {
4505 #$MPrefix .= "r";
4506 #}
4507 }
4508 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4509 $Mangled .= $Token;
4510 }
4511 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4512 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004513 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004514 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004515 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004516 foreach (@TPos) {
4517 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4518 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004519 }
4520 elsif($TmplParams)
4521 { # remangling mode
4522 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004523 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004524 }
4525 my $MangledNS = "";
4526 my ($SubNS, $SName) = get_sub_ns($ShortName);
4527 if($SubNS) {
4528 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4529 }
4530 $MangledNS .= length($SName).$SName;
4531 if(@TParams) {
4532 add_substitution($MangledNS, $Repl, 0);
4533 }
4534 $Mangled .= "N".$MangledNS;
4535 if(@TParams)
4536 { # templates
4537 $Mangled .= "I";
4538 foreach my $TParam (@TParams) {
4539 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4540 }
4541 $Mangled .= "E";
4542 }
4543 $Mangled .= "E";
4544 }
4545 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4546 {
4547 if($BaseType{"Type"} eq "MethodPtr") {
4548 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4549 }
4550 else {
4551 $Mangled .= "PF";
4552 }
4553 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4554 my @Params = keys(%{$BaseType{"Param"}});
4555 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4556 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4557 }
4558 if(not @Params) {
4559 $Mangled .= "v";
4560 }
4561 $Mangled .= "E";
4562 }
4563 elsif($BaseType{"Type"} eq "FieldPtr")
4564 {
4565 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4566 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4567 }
4568 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4569 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4570 {
4571 if($Mangled eq $Optimized)
4572 {
4573 if($ShortName!~/::/)
4574 { # remove "N ... E"
4575 if($MPrefix) {
4576 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4577 }
4578 else {
4579 $Mangled=~s/\AN(.+)E\Z/$1/g;
4580 }
4581 }
4582 }
4583 else {
4584 $Mangled = $Optimized;
4585 }
4586 }
4587 add_substitution($Mangled, $Repl, 1);
4588 return $Mangled;
4589}
4590
4591sub mangle_template_param($$$)
4592{ # types + literals
4593 my ($TParam, $LibVersion, $Repl) = @_;
4594 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4595 return mangle_param($TPTid, $LibVersion, $Repl);
4596 }
4597 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4598 { # class_name<1u>::method(...)
4599 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4600 }
4601 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4602 { # class_name<(signed char)1>::method(...)
4603 return "L".$IntrinsicMangling{$1}.$2."E";
4604 }
4605 elsif($TParam eq "true")
4606 { # class_name<true>::method(...)
4607 return "Lb1E";
4608 }
4609 elsif($TParam eq "false")
4610 { # class_name<true>::method(...)
4611 return "Lb0E";
4612 }
4613 else { # internal error
4614 return length($TParam).$TParam;
4615 }
4616}
4617
4618sub add_substitution($$$)
4619{
4620 my ($Value, $Repl, $Rec) = @_;
4621 if($Rec)
4622 { # subtypes
4623 my @Subs = ($Value);
4624 while($Value=~s/\A(R|P|K)//) {
4625 push(@Subs, $Value);
4626 }
4627 foreach (reverse(@Subs)) {
4628 add_substitution($_, $Repl, 0);
4629 }
4630 return;
4631 }
4632 return if($Value=~/\AS(\d*)_\Z/);
4633 $Value=~s/\AN(.+)E\Z/$1/g;
4634 return if(defined $Repl->{$Value});
4635 return if(length($Value)<=1);
4636 return if($StdcxxMangling{$Value});
4637 # check for duplicates
4638 my $Base = $Value;
4639 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4640 {
4641 my $Num = $Repl->{$Type};
4642 my $Replace = macro_mangle($Num);
4643 $Base=~s/\Q$Replace\E/$Type/;
4644 }
4645 if(my $OldNum = $Repl->{$Base})
4646 {
4647 $Repl->{$Value} = $OldNum;
4648 return;
4649 }
4650 my @Repls = sort {$b<=>$a} values(%{$Repl});
4651 if(@Repls) {
4652 $Repl->{$Value} = $Repls[0]+1;
4653 }
4654 else {
4655 $Repl->{$Value} = -1;
4656 }
4657 # register duplicates
4658 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004659 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004660 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4661 {
4662 next if($Base eq $Type);
4663 my $Num = $Repl->{$Type};
4664 my $Replace = macro_mangle($Num);
4665 $Base=~s/\Q$Type\E/$Replace/;
4666 $Repl->{$Base} = $Repl->{$Value};
4667 }
4668}
4669
4670sub macro_mangle($)
4671{
4672 my $Num = $_[0];
4673 if($Num==-1) {
4674 return "S_";
4675 }
4676 else
4677 {
4678 my $Code = "";
4679 if($Num<10)
4680 { # S0_, S1_, S2_, ...
4681 $Code = $Num;
4682 }
4683 elsif($Num>=10 and $Num<=35)
4684 { # SA_, SB_, SC_, ...
4685 $Code = chr(55+$Num);
4686 }
4687 else
4688 { # S10_, S11_, S12_
4689 $Code = $Num-26; # 26 is length of english alphabet
4690 }
4691 return "S".$Code."_";
4692 }
4693}
4694
4695sub write_stdcxx_substitution($)
4696{
4697 my $Mangled = $_[0];
4698 if($StdcxxMangling{$Mangled}) {
4699 return $StdcxxMangling{$Mangled};
4700 }
4701 else
4702 {
4703 my @Repls = keys(%StdcxxMangling);
4704 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4705 foreach my $MangledType (@Repls)
4706 {
4707 my $Replace = $StdcxxMangling{$MangledType};
4708 #if($Mangled!~/$Replace/) {
4709 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4710 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4711 #}
4712 }
4713 }
4714 return $Mangled;
4715}
4716
4717sub write_substitution($$)
4718{
4719 my ($Mangled, $Repl) = @_;
4720 if(defined $Repl->{$Mangled}
4721 and my $MnglNum = $Repl->{$Mangled}) {
4722 $Mangled = macro_mangle($MnglNum);
4723 }
4724 else
4725 {
4726 my @Repls = keys(%{$Repl});
4727 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4728 # FIXME: how to apply replacements? by num or by pos
4729 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4730 foreach my $MangledType (@Repls)
4731 {
4732 my $Replace = macro_mangle($Repl->{$MangledType});
4733 if($Mangled!~/$Replace/) {
4734 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4735 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4736 }
4737 }
4738 }
4739 return $Mangled;
4740}
4741
4742sub delete_keywords($)
4743{
4744 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004745 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004746 return $TypeName;
4747}
4748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004749sub uncover_typedefs($$)
4750{
4751 my ($TypeName, $LibVersion) = @_;
4752 return "" if(not $TypeName);
4753 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4754 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4755 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004756 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004757 while($TypeName_New ne $TypeName_Pre)
4758 {
4759 $TypeName_Pre = $TypeName_New;
4760 my $TypeName_Copy = $TypeName_New;
4761 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004762 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004763 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004764 if(not $Intrinsic_Keywords{$1}) {
4765 $Words{$1} = 1;
4766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004767 }
4768 foreach my $Word (keys(%Words))
4769 {
4770 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4771 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004772 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004773 if($BaseType_Name=~/\([\*]+\)/)
4774 { # FuncPtr
4775 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4776 {
4777 my $Type_Suffix = $1;
4778 $TypeName_New = $BaseType_Name;
4779 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004780 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004781 }
4782 }
4783 }
4784 else
4785 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004786 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004787 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004788 }
4789 }
4790 }
4791 }
4792 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4793}
4794
4795sub isInternal($)
4796{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004797 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4798 {
4799 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4800 {
4801 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4802 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4803 return 1;
4804 }
4805 }
4806 }
4807 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004808}
4809
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004810sub getDataVal($$)
4811{
4812 my ($InfoId, $TypeId) = @_;
4813 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4814 {
4815 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4816 {
4817 if(defined $LibInfo{$Version}{"info_type"}{$1}
4818 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004819 {
4820 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004821 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004822 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4823 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004824 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004825 if(my $Addr = getTreeAttr_Op($1)) {
4826 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004827 }
4828 }
4829 }
4830 }
4831 else {
4832 return getInitVal($1, $TypeId);
4833 }
4834 }
4835 }
4836 return undef;
4837}
4838
4839sub getInitVal($$)
4840{
4841 my ($InfoId, $TypeId) = @_;
4842 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4843 {
4844 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4845 {
4846 if($InfoType eq "integer_cst")
4847 {
4848 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004849 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004850 { # characters
4851 $Val = chr($Val);
4852 }
4853 return $Val;
4854 }
4855 elsif($InfoType eq "string_cst") {
4856 return getNodeStrCst($InfoId);
4857 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004858 elsif($InfoType eq "var_decl")
4859 {
4860 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4861 return $Name;
4862 }
4863 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004864 }
4865 }
4866 return undef;
4867}
4868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004869sub set_Class_And_Namespace($)
4870{
4871 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004872 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004873 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004874 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004875 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004876 my $NSInfoId = $1;
4877 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4878 {
4879 if($InfoType eq "namespace_decl") {
4880 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4881 }
4882 elsif($InfoType eq "record_type") {
4883 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4884 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004886 }
4887 }
4888 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4889 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004890 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004891 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004892 { # skip
4893 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004895 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004896
4897 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004898}
4899
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004900sub debugMangling($)
4901{
4902 my $LibVersion = $_[0];
4903 my %Mangled = ();
4904 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4905 {
4906 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4907 {
4908 if($Mngl=~/\A(_Z|\?)/) {
4909 $Mangled{$Mngl}=$InfoId;
4910 }
4911 }
4912 }
4913 translateSymbols(keys(%Mangled), $LibVersion);
4914 foreach my $Mngl (keys(%Mangled))
4915 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004916 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4917 my $U2 = $tr_name{$Mngl};
4918 if($U1 ne $U2) {
4919 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004920 }
4921 }
4922}
4923
4924sub linkSymbol($)
4925{ # link symbols from shared libraries
4926 # with the symbols from header files
4927 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004928 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004929 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004930 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4931 or $EMERGENCY_MODE_48)
4932 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4933 # 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 +03004934 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004935 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004936 {
4937 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4938 return correct_incharge($InfoId, $Version, $Mangled);
4939 }
4940 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004941 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004942 or not $BinaryOnly
4943 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004944 { # 1. --headers-only mode
4945 # 2. not mangled src-only symbols
4946 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4947 return $Mangled;
4948 }
4949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004950 }
4951 return "";
4952}
4953
4954sub setLanguage($$)
4955{
4956 my ($LibVersion, $Lang) = @_;
4957 if(not $UserLang) {
4958 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4959 }
4960}
4961
4962sub getSymbolInfo($)
4963{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004964 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004965 if(isInternal($InfoId)) {
4966 return;
4967 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004968 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4969 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004970 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4971 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004972 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004973 return;
4974 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004975 setFuncAccess($InfoId);
4976 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004977 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4978 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004979 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004980 return;
4981 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004982
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004983 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004984 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004985 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004986 if(not defined $TypeInfo{$Version}{$Return}
4987 or not $TypeInfo{$Version}{$Return}{"Name"})
4988 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004989 delete($SymbolInfo{$Version}{$InfoId});
4990 return;
4991 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004992 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004993 }
4994 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4995 {
4996 if(defined $MissedTypedef{$Version}{$Rid})
4997 {
4998 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4999 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5000 }
5001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005002 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005003 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5004 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005005 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005006 my $Orig = getFuncOrig($InfoId);
5007 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005008 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5009 {
5010 delete($SymbolInfo{$Version}{$InfoId});
5011 return;
5012 }
5013
5014 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005015 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005016 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005017 return;
5018 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005019
5020 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005021 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005022 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5023
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005024 my @TParams = getTParams($Orig, "Func");
5025 if(not @TParams)
5026 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005027 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005028 return;
5029 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005030 foreach my $Pos (0 .. $#TParams)
5031 {
5032 my $Val = $TParams[$Pos];
5033 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5034
5035 if($Tmpl)
5036 {
5037 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5038 {
5039 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5040 }
5041 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005042 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005043
5044 if($Tmpl)
5045 {
5046 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5047 {
5048 if($Pos>$#TParams)
5049 {
5050 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5051 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5052 }
5053 }
5054 }
5055
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005056 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5057 { # operator<< <T>, operator>> <T>
5058 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5059 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005060 if(@TParams) {
5061 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5062 }
5063 else {
5064 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5065 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005066 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005067 }
5068 else
5069 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005070 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005071 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005072 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5073 {
5074 if($OSgroup eq "windows")
5075 { # cut the offset
5076 $MnglName=~s/\@\d+\Z//g;
5077 }
5078 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5079
5080 # NOTE: mangling of some symbols may change depending on GCC version
5081 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5082 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5083 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005084
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005085 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005086 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005087 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005088 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005089 return;
5090 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005091 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005092 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005093 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005094 if($Skip)
5095 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005096 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005097 return;
5098 }
5099 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005100 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5101 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5102 }
5103
5104 if(set_Class_And_Namespace($InfoId))
5105 {
5106 delete($SymbolInfo{$Version}{$InfoId});
5107 return;
5108 }
5109
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005110 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5111 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005112 if(not defined $TypeInfo{$Version}{$ClassId}
5113 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005115 delete($SymbolInfo{$Version}{$InfoId});
5116 return;
5117 }
5118 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005119 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5120 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005122 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005123 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005124 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005126 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005127 }
5128 if($COMMON_LANGUAGE{$Version} eq "C++")
5129 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005130 # C++ or --headers-only mode
5131 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005132 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005133 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5134 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005135 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005136 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005137 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005138 if(my $Mangled = linkSymbol($InfoId)) {
5139 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005140 }
5141 }
5142 if($OStarget eq "windows")
5143 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005144 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005146 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005147 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005148 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005149 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005150 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005151 }
5152 }
5153 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005154 else
5155 { # not mangled in C
5156 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5157 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005158 if(not $CheckHeadersOnly
5159 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5160 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5161 {
5162 my $Incorrect = 0;
5163
5164 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5165 {
5166 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5167 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5168 { # mangled in the TU dump, but not mangled in the library
5169 $Incorrect = 1;
5170 }
5171 }
5172 else
5173 {
5174 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5175 { # all C++ functions are not mangled in the TU dump
5176 $Incorrect = 1;
5177 }
5178 }
5179 if($Incorrect)
5180 {
5181 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5182 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5183 }
5184 }
5185 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005186 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005187 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005188 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005189 return;
5190 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005191 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005192 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005193 { # identify virtual and pure virtual functions
5194 # NOTE: constructors cannot be virtual
5195 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5196 # in the TU dump, so taking it from the original symbol
5197 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5198 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5199 { # NOTE: D2 destructors are not present in a v-table
5200 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005203 if(isInline($InfoId)) {
5204 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005205 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005206 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005207 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005209 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5210 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005211 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005212 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005213 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005214 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005215 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005216 }
5217 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005218 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5219 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005220 if(not $ExtraDump)
5221 {
5222 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5223 { # non-target symbols
5224 delete($SymbolInfo{$Version}{$InfoId});
5225 return;
5226 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005229 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5230 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5231 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5232 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005234 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5235 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 return;
5238 }
5239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005240 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005241 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005242 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005243 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005244 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005245 return;
5246 }
5247 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 }
5250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5252 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5253 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005255 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5256 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005257 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005258 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 }
5262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 if(getFuncLink($InfoId) eq "Static") {
5264 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005266 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5267 {
5268 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5269 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005270 if($Unmangled=~/\.\_\d/)
5271 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005272 delete($SymbolInfo{$Version}{$InfoId});
5273 return;
5274 }
5275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005276 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005277
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005278 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5279 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005281 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5282 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005283 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005284
5285 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5286 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5287 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005288
5289 if($ExtraDump) {
5290 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5291 }
5292}
5293
5294sub guessHeader($)
5295{
5296 my $InfoId = $_[0];
5297 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5298 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5299 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5300 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5301 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5302 {
5303 if(get_filename($HPath) eq $Header)
5304 {
5305 my $HDir = get_filename(get_dirname($HPath));
5306 if($HDir ne "include"
5307 and $HDir=~/\A[a-z]+\Z/i) {
5308 return join_P($HDir, $Header);
5309 }
5310 }
5311 }
5312 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005313}
5314
5315sub isInline($)
5316{ # "body: undefined" in the tree
5317 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005318 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5319 {
5320 if($Info=~/ undefined /i) {
5321 return 0;
5322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005323 }
5324 return 1;
5325}
5326
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005327sub hasThrow($)
5328{
5329 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5330 {
5331 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5332 return getTreeAttr_Unql($1, "unql");
5333 }
5334 }
5335 return 1;
5336}
5337
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005338sub getTypeId($)
5339{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005340 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5341 {
5342 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5343 return $1;
5344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005345 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005346 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005347}
5348
5349sub setTypeMemb($$)
5350{
5351 my ($TypeId, $TypeAttr) = @_;
5352 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005353 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005354 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355 if($TypeType eq "Enum")
5356 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005357 my $MInfoId = getTreeAttr_Csts($TypeId);
5358 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005359 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005360 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5361 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005362 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005363 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5364 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005365 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366 }
5367 }
5368 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5369 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005370 my $MInfoId = getTreeAttr_Flds($TypeId);
5371 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005373 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5374 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005375 if(not $IType or $IType ne "field_decl")
5376 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005377
5378 if($IType eq "var_decl")
5379 { # static field
5380 $StaticFields = 1;
5381 }
5382
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005383 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005384 next;
5385 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005386 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005387 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005388 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005389 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 }
5391 if(not $StructMembName)
5392 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005393 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005395 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005396 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5397 if(isAnon($UnnamedTName))
5398 { # rename unnamed fields to unnamed0, unnamed1, ...
5399 $StructMembName = "unnamed".($UnnamedPos++);
5400 }
5401 }
5402 }
5403 if(not $StructMembName)
5404 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005405 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005406 next;
5407 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005408 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005409 if(defined $MissedTypedef{$Version}{$MembTypeId})
5410 {
5411 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5412 $MembTypeId = $AddedTid;
5413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005415
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005416 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5417 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005418 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005419 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005420 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5421 }
5422 if($MInfo=~/spec:\s*mutable /)
5423 { # mutable fields
5424 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005425 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005426 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005427 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5428 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005429 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005430 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005431 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 }
5433 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005434 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005435 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5436 { # template
5437 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5438 }
5439 else {
5440 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005442 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005443
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005444 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005445 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005446 }
5447 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005448
5449 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005450}
5451
5452sub setFuncParams($)
5453{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005454 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005455 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005456
5457 my $FType = getFuncType($InfoId);
5458
5459 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005460 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005461 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5462 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005463 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005464 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005465 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005467 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005468 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005471 else
5472 { # skip
5473 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005474 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005475 # skip "this"-parameter
5476 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005477 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005478 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005479 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005480 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005481 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5482 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5483 if(not $ParamName)
5484 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005485 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005487 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5488 {
5489 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5490 $ParamTypeId = $AddedTid;
5491 }
5492 }
5493 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005494 if(not $PType or $PType eq "Unknown") {
5495 return 1;
5496 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005497 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005498 if(not $PTName) {
5499 return 1;
5500 }
5501 if($PTName eq "void") {
5502 last;
5503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005505 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005506 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005507 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005508 $ParamInfoId = getNextElem($ParamInfoId);
5509 next;
5510 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005511 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005512
5513 if(my %Base = get_BaseType($ParamTypeId, $Version))
5514 {
5515 if(defined $Base{"Template"}) {
5516 return 1;
5517 }
5518 }
5519
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005520 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005521 if(my $Algn = getAlgn($ParamInfoId)) {
5522 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005524 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5525 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005526 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 }
5528 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005529 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005530 if($ParamName ne "this" or $FType ne "Method") {
5531 $PPos += 1;
5532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005533 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005534 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005535 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 }
5537 return 0;
5538}
5539
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005540sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005542 my ($InfoId, $Vtt_Pos) = @_;
5543 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005544 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005545 my $FType = getFuncType($InfoId);
5546
5547 if($FType eq "Method")
5548 {
5549 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005550 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005552 if(not $ParamListElemId)
5553 { # foo(...)
5554 return 1;
5555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005556 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005557 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005558 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005559 { # actual params: may differ from formal args
5560 # formal int*const
5561 # actual: int*
5562 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 {
5564 $Vtt_Pos=-1;
5565 $ParamListElemId = getNextElem($ParamListElemId);
5566 next;
5567 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005568 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5569 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005570 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 $HaveVoid = 1;
5572 last;
5573 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005574 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005575 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005576 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5577 {
5578 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5579 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5580 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005581 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005582 }
5583 }
5584 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5585 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005586 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005587 { # params
5588 if($OldId ne $ParamTypeId)
5589 {
5590 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5591 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5592
5593 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5594 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5595 }
5596 }
5597 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005598 }
5599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005600 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005601 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005602 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5603 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005604 if($PurpType eq "nop_expr")
5605 { # func ( const char* arg = (const char*)(void*)0 )
5606 $PurpId = getTreeAttr_Op($PurpId);
5607 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005608 my $Val = getInitVal($PurpId, $ParamTypeId);
5609 if(defined $Val) {
5610 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5611 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005612 }
5613 }
5614 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005615 if($Pos!=0 or $FType ne "Method") {
5616 $PPos += 1;
5617 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005618 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005619 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005620 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005621}
5622
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005623sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005624{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005625 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5626 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005627 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5628 return $1;
5629 }
5630 }
5631 return "";
5632}
5633
5634sub getTreeAttr_Chain($)
5635{
5636 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5637 {
5638 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5639 return $1;
5640 }
5641 }
5642 return "";
5643}
5644
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005645sub getTreeAttr_Unql($)
5646{
5647 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5648 {
5649 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5650 return $1;
5651 }
5652 }
5653 return "";
5654}
5655
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005656sub getTreeAttr_Scpe($)
5657{
5658 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5659 {
5660 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5661 return $1;
5662 }
5663 }
5664 return "";
5665}
5666
5667sub getTreeAttr_Type($)
5668{
5669 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5670 {
5671 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5672 return $1;
5673 }
5674 }
5675 return "";
5676}
5677
5678sub getTreeAttr_Name($)
5679{
5680 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5681 {
5682 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5683 return $1;
5684 }
5685 }
5686 return "";
5687}
5688
5689sub getTreeAttr_Mngl($)
5690{
5691 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5692 {
5693 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5694 return $1;
5695 }
5696 }
5697 return "";
5698}
5699
5700sub getTreeAttr_Prms($)
5701{
5702 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5703 {
5704 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5705 return $1;
5706 }
5707 }
5708 return "";
5709}
5710
5711sub getTreeAttr_Fncs($)
5712{
5713 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5714 {
5715 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5716 return $1;
5717 }
5718 }
5719 return "";
5720}
5721
5722sub getTreeAttr_Csts($)
5723{
5724 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5725 {
5726 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5727 return $1;
5728 }
5729 }
5730 return "";
5731}
5732
5733sub getTreeAttr_Purp($)
5734{
5735 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5736 {
5737 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5738 return $1;
5739 }
5740 }
5741 return "";
5742}
5743
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005744sub getTreeAttr_Op($)
5745{
5746 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5747 {
5748 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5749 return $1;
5750 }
5751 }
5752 return "";
5753}
5754
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005755sub getTreeAttr_Valu($)
5756{
5757 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5758 {
5759 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5760 return $1;
5761 }
5762 }
5763 return "";
5764}
5765
5766sub getTreeAttr_Flds($)
5767{
5768 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5769 {
5770 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5771 return $1;
5772 }
5773 }
5774 return "";
5775}
5776
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005777sub getTreeAttr_Binf($)
5778{
5779 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5780 {
5781 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5782 return $1;
5783 }
5784 }
5785 return "";
5786}
5787
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005788sub getTreeAttr_Args($)
5789{
5790 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5791 {
5792 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005793 return $1;
5794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005795 }
5796 return "";
5797}
5798
5799sub getTreeValue($)
5800{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005801 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5802 {
5803 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5804 return $1;
5805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005806 }
5807 return "";
5808}
5809
5810sub getTreeAccess($)
5811{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005812 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005813 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005814 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5815 {
5816 my $Access = $1;
5817 if($Access eq "prot") {
5818 return "protected";
5819 }
5820 elsif($Access eq "priv") {
5821 return "private";
5822 }
5823 }
5824 elsif($Info=~/ protected /)
5825 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005826 return "protected";
5827 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005828 elsif($Info=~/ private /)
5829 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005830 return "private";
5831 }
5832 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005833 return "public";
5834}
5835
5836sub setFuncAccess($)
5837{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005838 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005839 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005840 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005841 }
5842 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005843 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005844 }
5845}
5846
5847sub setTypeAccess($$)
5848{
5849 my ($TypeId, $TypeAttr) = @_;
5850 my $Access = getTreeAccess($TypeId);
5851 if($Access eq "protected") {
5852 $TypeAttr->{"Protected"} = 1;
5853 }
5854 elsif($Access eq "private") {
5855 $TypeAttr->{"Private"} = 1;
5856 }
5857}
5858
5859sub setFuncKind($)
5860{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005861 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5862 {
5863 if($Info=~/pseudo tmpl/) {
5864 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5865 }
5866 elsif($Info=~/ constructor /) {
5867 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5868 }
5869 elsif($Info=~/ destructor /) {
5870 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005872 }
5873}
5874
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005875sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005876{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005877 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5878 {
5879 if($Info=~/spec[ ]*:[ ]*pure /) {
5880 return "PureVirt";
5881 }
5882 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5883 return "Virt";
5884 }
5885 elsif($Info=~/ pure\s+virtual /)
5886 { # support for old GCC versions
5887 return "PureVirt";
5888 }
5889 elsif($Info=~/ virtual /)
5890 { # support for old GCC versions
5891 return "Virt";
5892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005893 }
5894 return "";
5895}
5896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897sub getFuncLink($)
5898{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005899 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5900 {
5901 if($Info=~/link[ ]*:[ ]*static /) {
5902 return "Static";
5903 }
5904 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005905 return $1;
5906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005907 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005908 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005909}
5910
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005911sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005912{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005913 my ($Symbol, $LibVersion) = @_;
5914 return "" if(not $Symbol or not $LibVersion);
5915 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5916 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005917 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005918 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5919 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5920 }
5921 }
5922 if($NS)
5923 {
5924 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5925 return $NS;
5926 }
5927 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005929 while($NS=~s/::[^:]+\Z//)
5930 {
5931 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5932 return $NS;
5933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005934 }
5935 }
5936 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005937
5938 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005939}
5940
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005941sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005942{
5943 my ($TypeName, $LibVersion) = @_;
5944 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005945 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005946 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005947 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5948 return $NS;
5949 }
5950 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005951 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005952 while($NS=~s/::[^:]+\Z//)
5953 {
5954 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5955 return $NS;
5956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005957 }
5958 }
5959 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005960 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005961}
5962
5963sub getNameSpace($)
5964{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005965 my $InfoId = $_[0];
5966 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005967 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005968 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005969 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005970 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005971 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005972 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5973 {
5974 my $NameSpace = getTreeStr($1);
5975 if($NameSpace eq "::")
5976 { # global namespace
5977 return "";
5978 }
5979 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5980 $NameSpace = $BaseNameSpace."::".$NameSpace;
5981 }
5982 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5983 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005984 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005985 else {
5986 return "";
5987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005988 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005989 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005990 { # inside data type
5991 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5992 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005996 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005997}
5998
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999sub getEnumMembVal($)
6000{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006001 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006002 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006003 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6004 {
6005 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6006 {
6007 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6008 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6009 return getTreeValue($1);
6010 }
6011 else
6012 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6013 return getTreeValue($1);
6014 }
6015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006016 }
6017 }
6018 return "";
6019}
6020
6021sub getSize($)
6022{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006023 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6024 {
6025 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6026 return getTreeValue($1);
6027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006028 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006029 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006030}
6031
6032sub getAlgn($)
6033{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006034 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6035 {
6036 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6037 return $1;
6038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006039 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006040 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006041}
6042
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006043sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006044{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006045 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6046 {
6047 if($Info=~/ bitfield /) {
6048 return getSize($_[0]);
6049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006051 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052}
6053
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006054sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006056 if(my $Chan = getTreeAttr_Chan($_[0])) {
6057 return $Chan;
6058 }
6059 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6060 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006062 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063}
6064
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006065sub registerHeader($$)
6066{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006067 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006068 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006069 return "";
6070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006071 if(is_abs($Header) and not -f $Header)
6072 { # incorrect absolute path
6073 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006075 if(skipHeader($Header, $LibVersion))
6076 { # skip
6077 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006078 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006079 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6080 {
6081 detect_header_includes($Header_Path, $LibVersion);
6082
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006083 if(defined $Tolerance and $Tolerance=~/3/)
6084 { # 3 - skip headers that include non-Linux headers
6085 if($OSgroup ne "windows")
6086 {
6087 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6088 {
6089 if(specificHeader($Inc, "windows")) {
6090 return "";
6091 }
6092 }
6093 }
6094 }
6095
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006096 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6097 { # redirect
6098 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6099 or skipHeader($RHeader_Path, $LibVersion))
6100 { # skip
6101 return "";
6102 }
6103 $Header_Path = $RHeader_Path;
6104 }
6105 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6106 { # skip
6107 return "";
6108 }
6109
6110 if(my $HName = get_filename($Header_Path))
6111 { # register
6112 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6113 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6114 }
6115
6116 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6117 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006118 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006119 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006120 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006121 }
6122
6123 if($CheckHeadersOnly
6124 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6125 { # /usr/include/c++/4.6.1/...
6126 $STDCXX_TESTING = 1;
6127 }
6128
6129 return $Header_Path;
6130 }
6131 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006132}
6133
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006134sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135{
6136 my ($Dir, $WithDeps, $LibVersion) = @_;
6137 $Dir=~s/[\/\\]+\Z//g;
6138 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006139 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006141 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006142 if($WithDeps)
6143 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006144 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6145 return;
6146 }
6147 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6148 $Mode = "DepsOnly";
6149 }
6150 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006151 else
6152 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006153 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6154 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6155 return;
6156 }
6157 }
6158 $Header_Dependency{$LibVersion}{$Dir} = 1;
6159 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6160 if($Mode eq "DepsOnly")
6161 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006162 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006163 $Header_Dependency{$LibVersion}{$Path} = 1;
6164 }
6165 return;
6166 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006167 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006168 {
6169 if($WithDeps)
6170 {
6171 my $SubDir = $Path;
6172 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6173 { # register all sub directories
6174 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6175 }
6176 }
6177 next if(is_not_header($Path));
6178 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006179 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006180 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006181 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6182 }
6183 }
6184 if(get_filename($Dir) eq "include")
6185 { # search for "lib/include/" directory
6186 my $LibDir = $Dir;
6187 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006188 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189 }
6190 }
6191}
6192
6193sub parse_redirect($$$)
6194{
6195 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 my @Errors = ();
6197 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6198 push(@Errors, $1);
6199 }
6200 my $Redirect = "";
6201 foreach (@Errors)
6202 {
6203 s/\s{2,}/ /g;
6204 if(/(only|must\ include
6205 |update\ to\ include
6206 |replaced\ with
6207 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006208 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006209 {
6210 $Redirect = $2;
6211 last;
6212 }
6213 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6214 {
6215 $Redirect = $2;
6216 last;
6217 }
6218 elsif(/this\ header\ should\ not\ be\ used
6219 |programs\ should\ not\ directly\ include
6220 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6221 |is\ not\ supported\ API\ for\ general\ use
6222 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006223 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006224 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6225 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6226 }
6227 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006228 if($Redirect)
6229 {
6230 $Redirect=~s/\A<//g;
6231 $Redirect=~s/>\Z//g;
6232 }
6233 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006234}
6235
6236sub parse_includes($$)
6237{
6238 my ($Content, $Path) = @_;
6239 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006240 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006241 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006242 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006243 my $Method = substr($Header, 0, 1, "");
6244 substr($Header, length($Header)-1, 1, "");
6245 $Header = path_format($Header, $OSgroup);
6246 if($Method eq "\"" or is_abs($Header))
6247 {
6248 if(-e join_P(get_dirname($Path), $Header))
6249 { # relative path exists
6250 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006251 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006252 else
6253 { # include "..." that doesn't exist is equal to include <...>
6254 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006257 else {
6258 $Includes{$Header} = 1;
6259 }
6260 }
6261 if($ExtraInfo)
6262 {
6263 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6264 { # FT_FREETYPE_H
6265 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006266 }
6267 }
6268 return \%Includes;
6269}
6270
6271sub ignore_path($)
6272{
6273 my $Path = $_[0];
6274 if($Path=~/\~\Z/)
6275 {# skipping system backup files
6276 return 1;
6277 }
6278 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6279 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6280 return 1;
6281 }
6282 return 0;
6283}
6284
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006285sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006286{
6287 my ($ArrRef, $W) = @_;
6288 return if(length($W)<2);
6289 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6290}
6291
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006292sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006293{
6294 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 $H1=~s/\.[a-z]+\Z//ig;
6297 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006298
6299 my $Hname1 = get_filename($H1);
6300 my $Hname2 = get_filename($H2);
6301 my $HDir1 = get_dirname($H1);
6302 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006303 my $Dirname1 = get_filename($HDir1);
6304 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006305
6306 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6307 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6308
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006309 if($_[0] eq $_[1]
6310 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006311 return 0;
6312 }
6313 elsif($H1=~/\A\Q$H2\E/) {
6314 return 1;
6315 }
6316 elsif($H2=~/\A\Q$H1\E/) {
6317 return -1;
6318 }
6319 elsif($HDir1=~/\Q$Hname1\E/i
6320 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006321 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322 return -1;
6323 }
6324 elsif($HDir2=~/\Q$Hname2\E/i
6325 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006326 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006327 return 1;
6328 }
6329 elsif($Hname1=~/\Q$Dirname1\E/i
6330 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006331 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 return -1;
6333 }
6334 elsif($Hname2=~/\Q$Dirname2\E/i
6335 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006336 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006337 return 1;
6338 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006339 elsif($Hname1=~/(config|lib|util)/i
6340 and $Hname2!~/(config|lib|util)/i)
6341 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006342 return -1;
6343 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006344 elsif($Hname2=~/(config|lib|util)/i
6345 and $Hname1!~/(config|lib|util)/i)
6346 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006347 return 1;
6348 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006349 else
6350 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006351 my $R1 = checkRelevance($H1);
6352 my $R2 = checkRelevance($H2);
6353 if($R1 and not $R2)
6354 { # libebook/e-book.h
6355 return -1;
6356 }
6357 elsif($R2 and not $R1)
6358 { # libebook/e-book.h
6359 return 1;
6360 }
6361 else
6362 {
6363 return (lc($H1) cmp lc($H2));
6364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006365 }
6366}
6367
6368sub searchForHeaders($)
6369{
6370 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006372 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006373 registerGccHeaders();
6374
6375 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6376 { # c++ standard include paths
6377 registerCppHeaders();
6378 }
6379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006380 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006381 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6382 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006383 {
6384 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006385 if($SystemRoot)
6386 {
6387 if(is_abs($Path)) {
6388 $Path = $SystemRoot.$Path;
6389 }
6390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 if(not -e $Path) {
6392 exitStatus("Access_Error", "can't access \'$Path\'");
6393 }
6394 elsif(-f $Path) {
6395 exitStatus("Access_Error", "\'$Path\' - not a directory");
6396 }
6397 elsif(-d $Path)
6398 {
6399 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006400 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006401 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6402 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006403 }
6404 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006405 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006406 }
6407 }
6408 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006409 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006410 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6411 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006413 # registering directories
6414 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6415 {
6416 next if(not -e $Path);
6417 $Path = get_abs_path($Path);
6418 $Path = path_format($Path, $OSgroup);
6419 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006420 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006421 }
6422 elsif(-f $Path)
6423 {
6424 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006425 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006426 and not $LocalIncludes{$Dir})
6427 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006428 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006429 # if(my $OutDir = get_dirname($Dir))
6430 # { # registering the outer directory
6431 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6432 # and not $LocalIncludes{$OutDir}) {
6433 # registerDir($OutDir, 0, $LibVersion);
6434 # }
6435 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006436 }
6437 }
6438 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006439
6440 # clean memory
6441 %RegisteredDirs = ();
6442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006443 # registering headers
6444 my $Position = 0;
6445 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6446 {
6447 if(is_abs($Dest) and not -e $Dest) {
6448 exitStatus("Access_Error", "can't access \'$Dest\'");
6449 }
6450 $Dest = path_format($Dest, $OSgroup);
6451 if(is_header($Dest, 1, $LibVersion))
6452 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006453 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006454 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6455 }
6456 }
6457 elsif(-d $Dest)
6458 {
6459 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006460 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006461 {
6462 next if(ignore_path($Path));
6463 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006464 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006465 push(@Registered, $HPath);
6466 }
6467 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006468 @Registered = sort {sortHeaders($a, $b)} @Registered;
6469 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 foreach my $Path (@Registered) {
6471 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6472 }
6473 }
6474 else {
6475 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6476 }
6477 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006478
6479 if(defined $Tolerance and $Tolerance=~/4/)
6480 { # 4 - skip headers included by others
6481 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6482 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006483 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006484 delete($Registered_Headers{$LibVersion}{$Path});
6485 }
6486 }
6487 }
6488
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006489 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6490 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006491 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006492 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006493 if(is_abs($Header) and not -f $Header) {
6494 exitStatus("Access_Error", "can't access file \'$Header\'");
6495 }
6496 $Header = path_format($Header, $OSgroup);
6497 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6498 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006499 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006500 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006501 }
6502 else {
6503 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006505 }
6506 }
6507 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6508 { # set relative paths (for duplicates)
6509 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6510 { # search for duplicates
6511 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6512 my $Prefix = get_dirname($FirstPath);
6513 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6514 { # detect a shortest distinguishing prefix
6515 my $NewPrefix = $1;
6516 my %Identity = ();
6517 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6518 {
6519 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6520 $Identity{$Path} = $1;
6521 }
6522 }
6523 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006524 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006525 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6526 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6527 }
6528 last;
6529 }
6530 $Prefix = $NewPrefix; # increase prefix
6531 }
6532 }
6533 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006534
6535 # clean memory
6536 %HeaderName_Paths = ();
6537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006538 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6539 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006540 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006541 my ($Pos, $PairPos) = (-1, -1);
6542 my ($Path, $PairPath) = ();
6543 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6544 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6545 foreach my $Header_Path (@Paths)
6546 {
6547 if(get_filename($Header_Path) eq $PairName)
6548 {
6549 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6550 $PairPath = $Header_Path;
6551 }
6552 if(get_filename($Header_Path) eq $HeaderName)
6553 {
6554 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6555 $Path = $Header_Path;
6556 }
6557 }
6558 if($PairPos!=-1 and $Pos!=-1
6559 and int($PairPos)<int($Pos))
6560 {
6561 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6562 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6563 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6564 }
6565 }
6566 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6567 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6568 }
6569}
6570
6571sub detect_real_includes($$)
6572{
6573 my ($AbsPath, $LibVersion) = @_;
6574 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6575 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6576 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6577 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6578 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006579 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6580
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006581 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6582 return () if(not $Path);
6583 open(PREPROC, $Path);
6584 while(<PREPROC>)
6585 {
6586 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6587 {
6588 my $Include = path_format($1, $OSgroup);
6589 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6590 next;
6591 }
6592 if($Include eq $AbsPath) {
6593 next;
6594 }
6595 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6596 }
6597 }
6598 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006599 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6600}
6601
6602sub detect_header_includes($$)
6603{
6604 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006605 return if(not $LibVersion or not $Path);
6606 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6607 return;
6608 }
6609 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6610
6611 if(not -e $Path) {
6612 return;
6613 }
6614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006615 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006616 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6617 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006618 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006619 {
6620 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006621 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006622 }
6623 if($RedirectPath ne $Path) {
6624 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6625 }
6626 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006627 else
6628 { # can't find
6629 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006631 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006632 if(my $Inc = parse_includes($Content, $Path))
6633 {
6634 foreach my $Include (keys(%{$Inc}))
6635 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006636 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006637
6638 if(defined $Tolerance and $Tolerance=~/4/)
6639 {
6640 if(my $HPath = identifyHeader($Include, $LibVersion))
6641 {
6642 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6643 }
6644 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006647}
6648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006649sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006650{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006651 my $Path = $_[0];
6652 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006653 if($OStarget eq "symbian")
6654 {
6655 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6656 { # epoc32/include/libc/{stdio, ...}.h
6657 return 1;
6658 }
6659 }
6660 else
6661 {
6662 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6663 { # /usr/include/{stdio, ...}.h
6664 return 1;
6665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 return 0;
6668}
6669
6670sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006671{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 my $Dir = $_[0];
6673 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006674 if($OStarget eq "symbian")
6675 {
6676 if(get_filename($OutDir) eq "libc"
6677 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6678 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6679 return 1;
6680 }
6681 }
6682 else
6683 { # linux
6684 if($OutDir eq "/usr/include"
6685 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6686 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6687 return 1;
6688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006689 }
6690 return 0;
6691}
6692
6693sub detect_recursive_includes($$)
6694{
6695 my ($AbsPath, $LibVersion) = @_;
6696 return () if(not $AbsPath);
6697 if(isCyclical(\@RecurInclude, $AbsPath)) {
6698 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6699 }
6700 my ($AbsDir, $Name) = separate_path($AbsPath);
6701 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006702 { # system GLIBC internals
6703 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704 }
6705 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6706 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6707 }
6708 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006709
6710 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6711 { # skip /usr/include/c++/*/ headers
6712 return () if(not $ExtraInfo);
6713 }
6714
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006715 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006716 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006717 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006718 { # check "real" (non-"model") include paths
6719 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6720 pop(@RecurInclude);
6721 return @Paths;
6722 }
6723 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6724 detect_header_includes($AbsPath, $LibVersion);
6725 }
6726 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6727 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006728 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006730 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006731 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006732 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006733 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006734 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006735 }
6736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006737 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006738 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006739 { # search for the nearest header
6740 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006741 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006742 if(-f $Candidate) {
6743 $HPath = $Candidate;
6744 }
6745 }
6746 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006747 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006748 }
6749 next if(not $HPath);
6750 if($HPath eq $AbsPath) {
6751 next;
6752 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006753
6754 if($Debug)
6755 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006756# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6757# {
6758# print STDERR "$AbsPath -> $HPath\n";
6759# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006760 }
6761
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006762 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6763 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006764 { # only include <...>, skip include "..." prefixes
6765 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6766 }
6767 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6768 {
6769 if($IncPath eq $AbsPath) {
6770 next;
6771 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006772 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6773 if($RIncType==-1)
6774 { # include "..."
6775 $RIncType = $IncType;
6776 }
6777 elsif($RIncType==2)
6778 {
6779 if($IncType!=-1) {
6780 $RIncType = $IncType;
6781 }
6782 }
6783 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006784 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6785 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6786 }
6787 }
6788 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6789 {
6790 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6791 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6792 { # distinguish math.h from glibc and math.h from the tested library
6793 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6794 last;
6795 }
6796 }
6797 }
6798 pop(@RecurInclude);
6799 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6800}
6801
6802sub find_in_framework($$$)
6803{
6804 my ($Header, $Framework, $LibVersion) = @_;
6805 return "" if(not $Header or not $Framework or not $LibVersion);
6806 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6807 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6808 }
6809 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6810 {
6811 if(get_filename($Dependency) eq $Framework
6812 and -f get_dirname($Dependency)."/".$Header) {
6813 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6814 }
6815 }
6816 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6817}
6818
6819sub find_in_defaults($)
6820{
6821 my $Header = $_[0];
6822 return "" if(not $Header);
6823 if(defined $Cache{"find_in_defaults"}{$Header}) {
6824 return $Cache{"find_in_defaults"}{$Header};
6825 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006826 foreach my $Dir (@DefaultIncPaths,
6827 @DefaultGccPaths,
6828 @DefaultCppPaths,
6829 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006830 {
6831 next if(not $Dir);
6832 if(-f $Dir."/".$Header) {
6833 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6834 }
6835 }
6836 return ($Cache{"find_in_defaults"}{$Header}="");
6837}
6838
6839sub cmp_paths($$)
6840{
6841 my ($Path1, $Path2) = @_;
6842 my @Parts1 = split(/[\/\\]/, $Path1);
6843 my @Parts2 = split(/[\/\\]/, $Path2);
6844 foreach my $Num (0 .. $#Parts1)
6845 {
6846 my $Part1 = $Parts1[$Num];
6847 my $Part2 = $Parts2[$Num];
6848 if($GlibcDir{$Part1}
6849 and not $GlibcDir{$Part2}) {
6850 return 1;
6851 }
6852 elsif($GlibcDir{$Part2}
6853 and not $GlibcDir{$Part1}) {
6854 return -1;
6855 }
6856 elsif($Part1=~/glib/
6857 and $Part2!~/glib/) {
6858 return 1;
6859 }
6860 elsif($Part1!~/glib/
6861 and $Part2=~/glib/) {
6862 return -1;
6863 }
6864 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6865 return $CmpRes;
6866 }
6867 }
6868 return 0;
6869}
6870
6871sub checkRelevance($)
6872{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006873 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006874 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006875
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006876 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006877 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006878 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006879
6880 my $Name = lc(get_filename($Path));
6881 my $Dir = lc(get_dirname($Path));
6882
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006883 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006884
6885 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006887 my $Len = length($Token);
6888 next if($Len<=1);
6889 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6890 { # include/evolution-data-server-1.4/libebook/e-book.h
6891 return 1;
6892 }
6893 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006894 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006895 return 1;
6896 }
6897 }
6898 return 0;
6899}
6900
6901sub checkFamily(@)
6902{
6903 my @Paths = @_;
6904 return 1 if($#Paths<=0);
6905 my %Prefix = ();
6906 foreach my $Path (@Paths)
6907 {
6908 if($SystemRoot) {
6909 $Path = cut_path_prefix($Path, $SystemRoot);
6910 }
6911 if(my $Dir = get_dirname($Path))
6912 {
6913 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6914 $Prefix{$Dir} += 1;
6915 $Prefix{get_dirname($Dir)} += 1;
6916 }
6917 }
6918 foreach (sort keys(%Prefix))
6919 {
6920 if(get_depth($_)>=3
6921 and $Prefix{$_}==$#Paths+1) {
6922 return 1;
6923 }
6924 }
6925 return 0;
6926}
6927
6928sub isAcceptable($$$)
6929{
6930 my ($Header, $Candidate, $LibVersion) = @_;
6931 my $HName = get_filename($Header);
6932 if(get_dirname($Header))
6933 { # with prefix
6934 return 1;
6935 }
6936 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6937 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6938 return 1;
6939 }
6940 if(checkRelevance($Candidate))
6941 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6942 return 1;
6943 }
6944 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6945 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6946 # /usr/include/qt4/Qt/qsslconfiguration.h
6947 return 1;
6948 }
6949 if($OStarget eq "symbian")
6950 {
6951 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6952 return 1;
6953 }
6954 }
6955 return 0;
6956}
6957
6958sub isRelevant($$$)
6959{ # disallow to search for "abstract" headers in too deep directories
6960 my ($Header, $Candidate, $LibVersion) = @_;
6961 my $HName = get_filename($Header);
6962 if($OStarget eq "symbian")
6963 {
6964 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6965 return 0;
6966 }
6967 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006968 if($OStarget ne "bsd")
6969 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006970 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6971 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6972 return 0;
6973 }
6974 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006975 if($OStarget ne "windows")
6976 {
6977 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6978 { # skip /usr/include/wine/msvcrt
6979 return 0;
6980 }
6981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006982 if(not get_dirname($Header)
6983 and $Candidate=~/[\/\\]wx[\/\\]/)
6984 { # do NOT search in system /wx/ directory
6985 # for headers without a prefix: sstream.h
6986 return 0;
6987 }
6988 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6989 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6990 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6991 return 0;
6992 }
6993 if($Candidate=~/[\/\\]asm-/
6994 and (my $Arch = getArch($LibVersion)) ne "unknown")
6995 { # arch-specific header files
6996 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6997 {# skip ../asm-arm/ if using x86 architecture
6998 return 0;
6999 }
7000 }
7001 my @Candidates = getSystemHeaders($HName, $LibVersion);
7002 if($#Candidates==1)
7003 { # unique header
7004 return 1;
7005 }
7006 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7007 if($#SCandidates==1)
7008 { # unique name
7009 return 1;
7010 }
7011 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7012 if(get_depth($Candidate)-$SystemDepth>=5)
7013 { # abstract headers in too deep directories
7014 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7015 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7016 return 0;
7017 }
7018 }
7019 if($Header eq "parser.h"
7020 and $Candidate!~/\/libxml2\//)
7021 { # select parser.h from xml2 library
7022 return 0;
7023 }
7024 if(not get_dirname($Header)
7025 and keys(%{$SystemHeaders{$HName}})>=3)
7026 { # many headers with the same name
7027 # like thread.h included without a prefix
7028 if(not checkFamily(@Candidates)) {
7029 return 0;
7030 }
7031 }
7032 return 1;
7033}
7034
7035sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007036{ # cache function
7037 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7038 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7039 }
7040 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7041}
7042
7043sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007044{
7045 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007046 if(-f $Header) {
7047 return $Header;
7048 }
7049 if(is_abs($Header) and not -f $Header)
7050 { # incorrect absolute path
7051 return "";
7052 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007053 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007054 { # too abstract configuration headers
7055 return "";
7056 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007057 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007058 if($OSgroup ne "windows")
7059 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007060 if(defined $WinHeaders{lc($HName)}
7061 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007062 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007063 return "";
7064 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007065 }
7066 if($OSgroup ne "macos")
7067 {
7068 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007069 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007070 return "";
7071 }
7072 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007073
7074 if(defined $ObsoleteHeaders{$HName})
7075 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007076 return "";
7077 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007078 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7079 {
7080 if(defined $AlienHeaders{$HName}
7081 or defined $AlienHeaders{$Header})
7082 { # alien headers from other systems
7083 return "";
7084 }
7085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007086
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007087 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007088 { # search in default paths
7089 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007090 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007091 }
7092 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007093 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007094 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007095 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007096 }
7097 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7098 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7099 {
7100 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007101 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007102 }
7103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007104 # error
7105 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007106}
7107
7108sub getSystemHeaders($$)
7109{
7110 my ($Header, $LibVersion) = @_;
7111 my @Candidates = ();
7112 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7113 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007114 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007115 next;
7116 }
7117 push(@Candidates, $Candidate);
7118 }
7119 return @Candidates;
7120}
7121
7122sub cut_path_prefix($$)
7123{
7124 my ($Path, $Prefix) = @_;
7125 return $Path if(not $Prefix);
7126 $Prefix=~s/[\/\\]+\Z//;
7127 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7128 return $Path;
7129}
7130
7131sub is_default_include_dir($)
7132{
7133 my $Dir = $_[0];
7134 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007135 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007136}
7137
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007138sub identifyHeader($$)
7139{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007140 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007141 if(not $Header) {
7142 return "";
7143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007144 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007145 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7146 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007147 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007148 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007149}
7150
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007152{ # search for header by absolute path, relative path or name
7153 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007154 if(-f $Header)
7155 { # it's relative or absolute path
7156 return get_abs_path($Header);
7157 }
7158 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7159 and my $HeaderDir = find_in_defaults($Header))
7160 { # search for libc headers in the /usr/include
7161 # for non-libc target library before searching
7162 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007163 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007164 }
7165 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7166 { # search in the target library paths
7167 return $Path;
7168 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007169 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 { # search in the internal GCC include paths
7171 return $DefaultGccHeader{$Header};
7172 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007173 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007174 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007175 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007176 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007177 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007178 { # search in the default G++ include paths
7179 return $DefaultCppHeader{$Header};
7180 }
7181 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7182 { # search everywhere in the system
7183 return $AnyPath;
7184 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007185 elsif($OSgroup eq "macos")
7186 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7187 if(my $Dir = get_dirname($Header))
7188 {
7189 my $RelPath = "Headers\/".get_filename($Header);
7190 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007191 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007192 }
7193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007194 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007195 # cannot find anything
7196 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197}
7198
7199sub getLocation($)
7200{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007201 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7202 {
7203 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007204 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007207 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007208}
7209
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007210sub getNameByInfo($)
7211{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007212 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007213 {
7214 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7215 {
7216 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7217 {
7218 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7219 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007220 my $Str = $1;
7221 if($CppMode{$Version}
7222 and $Str=~/\Ac99_(.+)\Z/)
7223 {
7224 if($CppKeywords_A{$1}) {
7225 $Str=$1;
7226 }
7227 }
7228 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007229 }
7230 }
7231 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007232 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007233 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007234}
7235
7236sub getTreeStr($)
7237{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007238 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007240 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7241 {
7242 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007243 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007244 and $Str=~/\Ac99_(.+)\Z/)
7245 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007246 if($CppKeywords_A{$1}) {
7247 $Str=$1;
7248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007249 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007250 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007252 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007253 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254}
7255
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007256sub getFuncShortName($)
7257{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007258 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007260 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007261 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007262 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007263 {
7264 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7265 {
7266 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7267 return "operator ".$RName;
7268 }
7269 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007270 }
7271 else
7272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007273 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7274 {
7275 if(my $Ind = $Operator_Indication{$1}) {
7276 return "operator".$Ind;
7277 }
7278 elsif(not $UnknownOperator{$1})
7279 {
7280 printMsg("WARNING", "unknown operator $1");
7281 $UnknownOperator{$1} = 1;
7282 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007283 }
7284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007285 }
7286 else
7287 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007288 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7289 return getTreeStr($1);
7290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007291 }
7292 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007293 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007294}
7295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007296sub getFuncReturn($)
7297{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007298 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7299 {
7300 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7301 {
7302 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7303 return $1;
7304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305 }
7306 }
7307 return "";
7308}
7309
7310sub getFuncOrig($)
7311{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007312 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7313 {
7314 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7315 return $1;
7316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007317 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007318 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007319}
7320
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321sub unmangleArray(@)
7322{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007323 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007324 { # MSVC mangling
7325 my $UndNameCmd = get_CmdPath("undname");
7326 if(not $UndNameCmd) {
7327 exitStatus("Not_Found", "can't find \"undname\"");
7328 }
7329 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007330 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331 }
7332 else
7333 { # GCC mangling
7334 my $CppFiltCmd = get_CmdPath("c++filt");
7335 if(not $CppFiltCmd) {
7336 exitStatus("Not_Found", "can't find c++filt in PATH");
7337 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007338 if(not defined $CPPFILT_SUPPORT_FILE)
7339 {
7340 my $Info = `$CppFiltCmd -h 2>&1`;
7341 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7342 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007343 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007344 if($CPPFILT_SUPPORT_FILE)
7345 { # new versions of c++filt can take a file
7346 if($#_>$MAX_CPPFILT_FILE_SIZE)
7347 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7348 # this is fixed in the oncoming version of Binutils
7349 my @Half = splice(@_, 0, ($#_+1)/2);
7350 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007352 else
7353 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007354 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7355 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7356 if($?==139)
7357 { # segmentation fault
7358 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7359 }
7360 return split(/\n/, $Res);
7361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 }
7363 else
7364 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007365 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7366 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367 my @Half = splice(@_, 0, ($#_+1)/2);
7368 return (unmangleArray(@Half), unmangleArray(@_))
7369 }
7370 else
7371 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007372 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007373 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7374 if($?==139)
7375 { # segmentation fault
7376 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7377 }
7378 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007379 }
7380 }
7381 }
7382}
7383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007384sub get_ChargeLevel($$)
7385{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007386 my ($Symbol, $LibVersion) = @_;
7387 return "" if($Symbol!~/\A(_Z|\?)/);
7388 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7389 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007390 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007391 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007392 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007393 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007394 return "[in-charge]";
7395 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007396 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 return "[not-in-charge]";
7398 }
7399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007400 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007402 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007403 return "[in-charge]";
7404 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007405 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 return "[not-in-charge]";
7407 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007408 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 return "[in-charge-deleting]";
7410 }
7411 }
7412 }
7413 else
7414 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007415 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 return "[in-charge]";
7417 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007418 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 return "[not-in-charge]";
7420 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007421 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007422 return "[in-charge]";
7423 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007424 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007425 return "[not-in-charge]";
7426 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007427 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007428 return "[in-charge-deleting]";
7429 }
7430 }
7431 return "";
7432}
7433
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007434sub get_Signature_M($$)
7435{
7436 my ($Symbol, $LibVersion) = @_;
7437 my $Signature_M = $tr_name{$Symbol};
7438 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7439 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007440 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007441 }
7442 return $Signature_M;
7443}
7444
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007445sub get_Signature($$)
7446{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007447 my ($Symbol, $LibVersion) = @_;
7448 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7449 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007451 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007452 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007453
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007454 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007455
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007456 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007458 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7459 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007460 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7461 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007462
7463 if(index($Symbol, "_ZTV")==0) {
7464 return "vtable for $ClassName [data]";
7465 }
7466
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007467 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007468 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7469 $Signature .= "~";
7470 }
7471 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007473 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007474 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 }
7476 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007477 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007479 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7480 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007482 else
7483 {
7484 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 }
7486 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007487 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007489 if($Pos eq "") {
7490 next;
7491 }
7492
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007493 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007494 if(not $ParamTypeId) {
7495 next;
7496 }
7497
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007498 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499 if(not $ParamTypeName) {
7500 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7501 }
7502 foreach my $Typedef (keys(%ChangedTypedef))
7503 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007504 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7505 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007507 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007508 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7509 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007510 if($ParamName eq "this"
7511 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007512 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007513 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007514 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007515 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007516 }
7517 else {
7518 push(@ParamArray, $ParamTypeName);
7519 }
7520 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007521 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7522 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007523 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 }
7525 else
7526 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007527 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007529 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007531 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007532 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7533 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007534 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007536 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7537 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007538 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007540 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7541 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007542 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007543 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 }
7545 }
7546 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007547 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007548 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007549 }
7550 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007551 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007553 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007554}
7555
7556sub create_member_decl($$)
7557{
7558 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007559 if($TName=~/\([\*]+\)/)
7560 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7562 return $TName;
7563 }
7564 else
7565 {
7566 my @ArraySizes = ();
7567 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7568 push(@ArraySizes, $1);
7569 }
7570 return $TName." ".$Member.join("", @ArraySizes);
7571 }
7572}
7573
7574sub getFuncType($)
7575{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007576 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7577 {
7578 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7579 {
7580 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7581 {
7582 if($Type eq "method_type") {
7583 return "Method";
7584 }
7585 elsif($Type eq "function_type") {
7586 return "Function";
7587 }
7588 else {
7589 return "Other";
7590 }
7591 }
7592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007594 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595}
7596
7597sub getFuncTypeId($)
7598{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007599 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7600 {
7601 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7602 return $1;
7603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007605 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007606}
7607
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007609{ # "._N" or "$_N" in older GCC versions
7610 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007611}
7612
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007613sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007614{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007615 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7616 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007617 }
7618
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007619 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007620
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007621 if($_[1] ne "S")
7622 {
7623 $N=~s/\A[ ]+//g;
7624 $N=~s/[ ]+\Z//g;
7625 $N=~s/[ ]{2,}/ /g;
7626 }
7627
7628 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007629
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007630 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7631
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007632 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007633
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007634 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7635 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007636
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007637 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007639 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007640
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007641 if($_[1] eq "S")
7642 {
7643 if(index($N, "operator")!=-1) {
7644 $N=~s/\b(operator[ ]*)> >/$1>>/;
7645 }
7646 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007647
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007648 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007649
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007650 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007651}
7652
7653sub get_HeaderDeps($$)
7654{
7655 my ($AbsPath, $LibVersion) = @_;
7656 return () if(not $AbsPath or not $LibVersion);
7657 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7658 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7659 }
7660 my %IncDir = ();
7661 detect_recursive_includes($AbsPath, $LibVersion);
7662 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7663 {
7664 next if(not $HeaderPath);
7665 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7666 my $Dir = get_dirname($HeaderPath);
7667 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7668 {
7669 my $Dep = $Dir;
7670 if($Prefix)
7671 {
7672 if($OSgroup eq "windows")
7673 { # case insensitive seach on windows
7674 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7675 next;
7676 }
7677 }
7678 elsif($OSgroup eq "macos")
7679 { # seach in frameworks
7680 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7681 {
7682 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7683 {# frameworks
7684 my ($HFramework, $HName) = ($1, $2);
7685 $Dep = $HFramework;
7686 }
7687 else
7688 {# mismatch
7689 next;
7690 }
7691 }
7692 }
7693 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7694 { # Linux, FreeBSD
7695 next;
7696 }
7697 }
7698 if(not $Dep)
7699 { # nothing to include
7700 next;
7701 }
7702 if(is_default_include_dir($Dep))
7703 { # included by the compiler
7704 next;
7705 }
7706 if(get_depth($Dep)==1)
7707 { # too short
7708 next;
7709 }
7710 if(isLibcDir($Dep))
7711 { # do NOT include /usr/include/{sys,bits}
7712 next;
7713 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007714 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007715 }
7716 }
7717 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7718 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7719}
7720
7721sub sortIncPaths($$)
7722{
7723 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007724 if(not $ArrRef or $#{$ArrRef}<0) {
7725 return $ArrRef;
7726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007727 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7728 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007729 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007730 return $ArrRef;
7731}
7732
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007733sub sortDeps($$$)
7734{
7735 if($Header_Dependency{$_[2]}{$_[0]}
7736 and not $Header_Dependency{$_[2]}{$_[1]}) {
7737 return 1;
7738 }
7739 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7740 and $Header_Dependency{$_[2]}{$_[1]}) {
7741 return -1;
7742 }
7743 return 0;
7744}
7745
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007746sub join_P($$)
7747{
7748 my $S = "/";
7749 if($OSgroup eq "windows") {
7750 $S = "\\";
7751 }
7752 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007753}
7754
7755sub get_namespace_additions($)
7756{
7757 my $NameSpaces = $_[0];
7758 my ($Additions, $AddNameSpaceId) = ("", 1);
7759 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7760 {
7761 next if($SkipNameSpaces{$Version}{$NS});
7762 next if(not $NS or $NameSpaces->{$NS}==-1);
7763 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7764 next if($NS=~/\A__/i);
7765 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007766 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007767 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7768 my @NS_Parts = split(/::/, $NS);
7769 next if($#NS_Parts==-1);
7770 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7771 foreach my $NS_Part (@NS_Parts)
7772 {
7773 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7774 $TypeDecl_Suffix .= "}";
7775 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007776 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007777 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7778 $Additions.=" $TypeDecl\n $FuncDecl\n";
7779 $AddNameSpaceId+=1;
7780 }
7781 return $Additions;
7782}
7783
7784sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007785{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007786 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007787 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007788 if($Fmt eq "windows")
7789 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007790 $Path=~s/\//\\/g;
7791 $Path=lc($Path);
7792 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007793 else
7794 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007795 $Path=~s/\\/\//g;
7796 }
7797 return $Path;
7798}
7799
7800sub inc_opt($$)
7801{
7802 my ($Path, $Style) = @_;
7803 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007804 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007805 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007806 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007807 return "-I\"".path_format($Path, "unix")."\"";
7808 }
7809 elsif($OSgroup eq "macos"
7810 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007811 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007812 return "-F".esc(get_dirname($Path));
7813 }
7814 else {
7815 return "-I".esc($Path);
7816 }
7817 }
7818 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007819 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007820 }
7821 return "";
7822}
7823
7824sub platformSpecs($)
7825{
7826 my $LibVersion = $_[0];
7827 my $Arch = getArch($LibVersion);
7828 if($OStarget eq "symbian")
7829 { # options for GCCE compiler
7830 my %Symbian_Opts = map {$_=>1} (
7831 "-D__GCCE__",
7832 "-DUNICODE",
7833 "-fexceptions",
7834 "-D__SYMBIAN32__",
7835 "-D__MARM_INTERWORK__",
7836 "-D_UNICODE",
7837 "-D__S60_50__",
7838 "-D__S60_3X__",
7839 "-D__SERIES60_3X__",
7840 "-D__EPOC32__",
7841 "-D__MARM__",
7842 "-D__EABI__",
7843 "-D__MARM_ARMV5__",
7844 "-D__SUPPORT_CPP_EXCEPTIONS__",
7845 "-march=armv5t",
7846 "-mapcs",
7847 "-mthumb-interwork",
7848 "-DEKA2",
7849 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7850 );
7851 return join(" ", keys(%Symbian_Opts));
7852 }
7853 elsif($OSgroup eq "windows"
7854 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7855 { # add options to MinGW compiler
7856 # to simulate the MSVC compiler
7857 my %MinGW_Opts = map {$_=>1} (
7858 "-D_WIN32",
7859 "-D_STDCALL_SUPPORTED",
7860 "-D__int64=\"long long\"",
7861 "-D__int32=int",
7862 "-D__int16=short",
7863 "-D__int8=char",
7864 "-D__possibly_notnullterminated=\" \"",
7865 "-D__nullterminated=\" \"",
7866 "-D__nullnullterminated=\" \"",
7867 "-D__w64=\" \"",
7868 "-D__ptr32=\" \"",
7869 "-D__ptr64=\" \"",
7870 "-D__forceinline=inline",
7871 "-D__inline=inline",
7872 "-D__uuidof(x)=IID()",
7873 "-D__try=",
7874 "-D__except(x)=",
7875 "-D__declspec(x)=__attribute__((x))",
7876 "-D__pragma(x)=",
7877 "-D_inline=inline",
7878 "-D__forceinline=__inline",
7879 "-D__stdcall=__attribute__((__stdcall__))",
7880 "-D__cdecl=__attribute__((__cdecl__))",
7881 "-D__fastcall=__attribute__((__fastcall__))",
7882 "-D__thiscall=__attribute__((__thiscall__))",
7883 "-D_stdcall=__attribute__((__stdcall__))",
7884 "-D_cdecl=__attribute__((__cdecl__))",
7885 "-D_fastcall=__attribute__((__fastcall__))",
7886 "-D_thiscall=__attribute__((__thiscall__))",
7887 "-DSHSTDAPI_(x)=x",
7888 "-D_MSC_EXTENSIONS",
7889 "-DSECURITY_WIN32",
7890 "-D_MSC_VER=1500",
7891 "-D_USE_DECLSPECS_FOR_SAL",
7892 "-D__noop=\" \"",
7893 "-DDECLSPEC_DEPRECATED=\" \"",
7894 "-D__builtin_alignof(x)=__alignof__(x)",
7895 "-DSORTPP_PASS");
7896 if($Arch eq "x86") {
7897 $MinGW_Opts{"-D_M_IX86=300"}=1;
7898 }
7899 elsif($Arch eq "x86_64") {
7900 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7901 }
7902 elsif($Arch eq "ia64") {
7903 $MinGW_Opts{"-D_M_IA64=300"}=1;
7904 }
7905 return join(" ", keys(%MinGW_Opts));
7906 }
7907 return "";
7908}
7909
7910my %C_Structure = map {$_=>1} (
7911# FIXME: Can't separate union and struct data types before dumping,
7912# so it sometimes cause compilation errors for unknown reason
7913# when trying to declare TYPE* tmp_add_class_N
7914# This is a list of such structures + list of other C structures
7915 "sigval",
7916 "sigevent",
7917 "sigaction",
7918 "sigvec",
7919 "sigstack",
7920 "timeval",
7921 "timezone",
7922 "rusage",
7923 "rlimit",
7924 "wait",
7925 "flock",
7926 "stat",
7927 "_stat",
7928 "stat32",
7929 "_stat32",
7930 "stat64",
7931 "_stat64",
7932 "_stati64",
7933 "if_nameindex",
7934 "usb_device",
7935 "sigaltstack",
7936 "sysinfo",
7937 "timeLocale",
7938 "tcp_debug",
7939 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007940 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007941 "timespec",
7942 "random_data",
7943 "drand48_data",
7944 "_IO_marker",
7945 "_IO_FILE",
7946 "lconv",
7947 "sched_param",
7948 "tm",
7949 "itimerspec",
7950 "_pthread_cleanup_buffer",
7951 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007952 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007953 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007954 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007955 "sigcontext",
7956 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007957 # Mac
7958 "_timex",
7959 "_class_t",
7960 "_category_t",
7961 "_class_ro_t",
7962 "_protocol_t",
7963 "_message_ref_t",
7964 "_super_message_ref_t",
7965 "_ivar_t",
7966 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007967);
7968
7969sub getCompileCmd($$$)
7970{
7971 my ($Path, $Opt, $Inc) = @_;
7972 my $GccCall = $GCC_PATH;
7973 if($Opt) {
7974 $GccCall .= " ".$Opt;
7975 }
7976 $GccCall .= " -x ";
7977 if($OSgroup eq "macos") {
7978 $GccCall .= "objective-";
7979 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007980
7981 if($EMERGENCY_MODE_48)
7982 { # workaround for GCC 4.8 (C only)
7983 $GccCall .= "c++";
7984 }
7985 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007986 { # compile as "C++" header
7987 # to obtain complete dump using GCC 4.0
7988 $GccCall .= "c++-header";
7989 }
7990 else
7991 { # compile as "C++" source
7992 # GCC 3.3 cannot compile headers
7993 $GccCall .= "c++";
7994 }
7995 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007996 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007997 $GccCall .= " ".$Opts;
7998 }
7999 # allow extra qualifications
8000 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008001 $GccCall .= " -fpermissive";
8002 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008003 if($NoStdInc)
8004 {
8005 $GccCall .= " -nostdinc";
8006 $GccCall .= " -nostdinc++";
8007 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008008 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008009 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008010 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008011 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008012 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008013 if($Inc)
8014 { # include paths
8015 $GccCall .= " ".$Inc;
8016 }
8017 return $GccCall;
8018}
8019
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008020sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008021{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008022 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008023 my %HeaderElems = (
8024 # Types
8025 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008026 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008027 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8028 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008029 "time.h" => ["time_t"],
8030 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008031 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8032 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008033 "stdbool.h" => ["_Bool"],
8034 "rpc/xdr.h" => ["bool_t"],
8035 "in_systm.h" => ["n_long", "n_short"],
8036 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008037 "arpa/inet.h" => ["fw_src", "ip_src"],
8038 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008039 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008040 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008041 );
8042 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008043 foreach (keys(%HeaderElems))
8044 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008045 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008046 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008047 }
8048 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008049 my %Types = ();
8050 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8051 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008052 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008053 }
8054 if(keys(%Types))
8055 {
8056 my %AddHeaders = ();
8057 foreach my $Type (keys(%Types))
8058 {
8059 if(my $Header = $AutoPreamble{$Type})
8060 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008061 if(my $Path = identifyHeader($Header, $LibVersion))
8062 {
8063 if(skipHeader($Path, $LibVersion)) {
8064 next;
8065 }
8066 $Path = path_format($Path, $OSgroup);
8067 $AddHeaders{$Path}{"Type"} = $Type;
8068 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008069 }
8070 }
8071 }
8072 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008073 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008074 }
8075 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008076 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008077}
8078
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008079sub checkCTags($)
8080{
8081 my $Path = $_[0];
8082 if(not $Path) {
8083 return;
8084 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008085 my $CTags = undef;
8086
8087 if($OSgroup eq "bsd")
8088 { # use ectags on BSD
8089 $CTags = get_CmdPath("ectags");
8090 if(not $CTags) {
8091 printMsg("WARNING", "can't find \'ectags\' program");
8092 }
8093 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008094 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008095 $CTags = get_CmdPath("ctags");
8096 }
8097 if(not $CTags)
8098 {
8099 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008100 return;
8101 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008102
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008103 if($OSgroup ne "linux")
8104 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008105 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8106 if($Info!~/exuberant/i)
8107 {
8108 printMsg("WARNING", "incompatible version of \'ctags\' program");
8109 return;
8110 }
8111 }
8112
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008113 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008114 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008115 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008116 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008117 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008118 open(CTAGS, "<", $Out);
8119 while(my $Line = <CTAGS>)
8120 {
8121 chomp($Line);
8122 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008123 if(defined $Intrinsic_Keywords{$Name})
8124 { # noise
8125 next;
8126 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008127 if($Type eq "n")
8128 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008129 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008130 next;
8131 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008132 if(index($Scpe, "struct:")==0) {
8133 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008134 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008135 if(index($Scpe, "namespace:")==0)
8136 {
8137 if($Scpe=~s/\Anamespace://) {
8138 $Name = $Scpe."::".$Name;
8139 }
8140 }
8141 $TUnit_NameSpaces{$Version}{$Name} = 1;
8142 }
8143 elsif($Type eq "p")
8144 {
8145 if(not $Scpe or index($Scpe, "namespace:")==0) {
8146 $TUnit_Funcs{$Version}{$Name} = 1;
8147 }
8148 }
8149 elsif($Type eq "x")
8150 {
8151 if(not $Scpe or index($Scpe, "namespace:")==0) {
8152 $TUnit_Vars{$Version}{$Name} = 1;
8153 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008154 }
8155 }
8156 close(CTAGS);
8157}
8158
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008159sub preChange($$)
8160{
8161 my ($HeaderPath, $IncStr) = @_;
8162
8163 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8164 my $Content = undef;
8165
8166 if($OStarget eq "windows"
8167 and get_dumpmachine($GCC_PATH)=~/mingw/i
8168 and $MinGWMode{$Version}!=-1)
8169 { # modify headers to compile by MinGW
8170 if(not $Content)
8171 { # preprocessing
8172 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8173 }
8174 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8175 { # __asm { ... }
8176 $MinGWMode{$Version}=1;
8177 }
8178 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8179 { # comments after preprocessing
8180 $MinGWMode{$Version}=1;
8181 }
8182 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8183 { # 0xffui8
8184 $MinGWMode{$Version}=1;
8185 }
8186
8187 if($MinGWMode{$Version}) {
8188 printMsg("INFO", "Using MinGW compatibility mode");
8189 }
8190 }
8191
8192 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8193 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8194 { # rename C++ keywords in C code
8195 # disable this code by -cpp-compatible option
8196 if(not $Content)
8197 { # preprocessing
8198 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8199 }
8200 my $RegExp_C = join("|", keys(%CppKeywords_C));
8201 my $RegExp_F = join("|", keys(%CppKeywords_F));
8202 my $RegExp_O = join("|", keys(%CppKeywords_O));
8203
8204 my $Detected = undef;
8205
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008206 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 +04008207 { # MATCH:
8208 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008209 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008210 # unsigned private: 8;
8211 # DO NOT MATCH:
8212 # #pragma GCC visibility push(default)
8213 $CppMode{$Version} = 1;
8214 $Detected = "$1$2$3$4" if(not defined $Detected);
8215 }
8216 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8217 { # MATCH:
8218 # int delete(...);
8219 # int explicit(...);
8220 # DO NOT MATCH:
8221 # void operator delete(...)
8222 $CppMode{$Version} = 1;
8223 $Detected = "$1$2$3" if(not defined $Detected);
8224 }
8225 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8226 { # MATCH:
8227 # int bool;
8228 # DO NOT MATCH:
8229 # bool X;
8230 # return *this;
8231 # throw;
8232 $CppMode{$Version} = 1;
8233 $Detected = "$1$2$3" if(not defined $Detected);
8234 }
8235 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8236 { # MATCH:
8237 # int operator(...);
8238 # DO NOT MATCH:
8239 # int operator()(...);
8240 $CppMode{$Version} = 1;
8241 $Detected = "$1$2$3" if(not defined $Detected);
8242 }
8243 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8244 { # MATCH:
8245 # int foo(int operator);
8246 # int foo(int operator, int other);
8247 # DO NOT MATCH:
8248 # int operator,(...);
8249 $CppMode{$Version} = 1;
8250 $Detected = "$1$2$3" if(not defined $Detected);
8251 }
8252 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8253 { # MATCH:
8254 # int foo(gboolean *bool);
8255 # DO NOT MATCH:
8256 # void setTabEnabled(int index, bool);
8257 $CppMode{$Version} = 1;
8258 $Detected = "$1$2$3" if(not defined $Detected);
8259 }
8260 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8261 { # MATCH:
8262 # int foo(int* this);
8263 # int bar(int this);
8264 # int baz(int throw);
8265 # DO NOT MATCH:
8266 # foo(X, this);
8267 $CppMode{$Version} = 1;
8268 $Detected = "$1$2$3$4" if(not defined $Detected);
8269 }
8270 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8271 { # MATCH:
8272 # struct template {...};
8273 # extern template foo(...);
8274 $CppMode{$Version} = 1;
8275 $Detected = "$1$2" if(not defined $Detected);
8276 }
8277
8278 if($CppMode{$Version} == 1)
8279 {
8280 if($Debug)
8281 {
8282 $Detected=~s/\A\s+//g;
8283 printMsg("INFO", "Detected code: \"$Detected\"");
8284 }
8285 }
8286
8287 # remove typedef enum NAME NAME;
8288 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8289 my $N = 0;
8290 while($N<=$#FwdTypedefs-1)
8291 {
8292 my $S = $FwdTypedefs[$N];
8293 if($S eq $FwdTypedefs[$N+1])
8294 {
8295 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008296 $CppMode{$Version} = 1;
8297
8298 if($Debug) {
8299 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8300 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008301 }
8302 $N+=2;
8303 }
8304
8305 if($CppMode{$Version}==1) {
8306 printMsg("INFO", "Using C++ compatibility mode");
8307 }
8308 }
8309
8310 if($CppMode{$Version}==1
8311 or $MinGWMode{$Version}==1)
8312 {
8313 my $IPath = $TMP_DIR."/dump$Version.i";
8314 writeFile($IPath, $Content);
8315 return $IPath;
8316 }
8317
8318 return undef;
8319}
8320
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008321sub getDump()
8322{
8323 if(not $GCC_PATH) {
8324 exitStatus("Error", "internal error - GCC path is not set");
8325 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008326
8327 my @Headers = keys(%{$Registered_Headers{$Version}});
8328 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8329
8330 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8331
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008332 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008333 my $HeaderPath = $TmpHeaderPath;
8334
8335 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008336 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008337 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8338 {
8339 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008340 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008341 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008342 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008343 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8344 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008345 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008346 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008347 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008348 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8349 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008351 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008352 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008353
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008354 if($ExtraInfo)
8355 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008356 if($IncludeString) {
8357 writeFile($ExtraInfo."/include-string", $IncludeString);
8358 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008359 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8360 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008361
8362 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8363 {
8364 my $REDIR = "";
8365 foreach my $P1 (sort @Redirects) {
8366 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8367 }
8368 writeFile($ExtraInfo."/include-redirect", $REDIR);
8369 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008370 }
8371
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008372 if(not keys(%{$TargetHeaders{$Version}}))
8373 { # Target headers
8374 addTargetHeaders($Version);
8375 }
8376
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008377 # clean memory
8378 %RecursiveIncludes = ();
8379 %Header_Include_Prefix = ();
8380 %Header_Includes = ();
8381
8382 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008383 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008384 delete($Cache{"detect_header_includes"});
8385 delete($Cache{"selectSystemHeader"});
8386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008387 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008388 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8389 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008390
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008391 if($ExtraInfo)
8392 { # extra information for other tools
8393 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8394 }
8395
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008396 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008397 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008398 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008399
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008400 if($COMMON_LANGUAGE{$Version} eq "C++") {
8401 checkCTags($Pre);
8402 }
8403
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008404 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8405 { # try to correct the preprocessor output
8406 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008408
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008409 if($COMMON_LANGUAGE{$Version} eq "C++")
8410 { # add classes and namespaces to the dump
8411 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008412 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008413 or $MinGWMode{$Version}==1) {
8414 $CHdump .= " -fpreprocessed";
8415 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008416 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008417 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008418 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008419 chdir($ORIG_DIR);
8420 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8421 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008422 my $Content = readFile($ClassDump);
8423 foreach my $ClassInfo (split(/\n\n/, $Content))
8424 {
8425 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8426 {
8427 my $CName = $1;
8428 next if($CName=~/\A(__|_objc_|_opaque_)/);
8429 $TUnit_NameSpaces{$Version}{$CName} = -1;
8430 if($CName=~/\A[\w:]+\Z/)
8431 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008432 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 }
8434 if($CName=~/(\w[\w:]*)::/)
8435 { # namespaces
8436 my $NS = $1;
8437 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8438 $TUnit_NameSpaces{$Version}{$NS} = 1;
8439 }
8440 }
8441 }
8442 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8443 { # read v-tables (advanced approach)
8444 my ($CName, $VTable) = ($1, $2);
8445 $ClassVTable_Content{$Version}{$CName} = $VTable;
8446 }
8447 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008448 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8449 { # add user-defined namespaces
8450 $TUnit_NameSpaces{$Version}{$NS} = 1;
8451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008452 if($Debug)
8453 { # debug mode
8454 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008455 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008456 }
8457 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008458 }
8459
8460 # add namespaces and classes
8461 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8462 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008463 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008464 }
8465 # some GCC versions don't include class methods to the TU dump by default
8466 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008467 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008468 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8469 {
8470 next if($C_Structure{$CName});
8471 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008472 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008473 if(not $Force and $GCC_44
8474 and $OSgroup eq "linux")
8475 { # optimization for linux with GCC >= 4.4
8476 # disable this code by -force option
8477 if(index($CName, "::")!=-1)
8478 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008479 next;
8480 }
8481 }
8482 else
8483 {
8484 if($CName=~/\A(.+)::[^:]+\Z/
8485 and $TUnit_Classes{$Version}{$1})
8486 { # classes inside other classes
8487 next;
8488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008489 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008490 if(defined $TUnit_Funcs{$Version}{$CName})
8491 { # the same name for a function and type
8492 next;
8493 }
8494 if(defined $TUnit_Vars{$Version}{$CName})
8495 { # the same name for a variable and type
8496 next;
8497 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008498 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8499 }
8500 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008501 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008502 }
8503 }
8504 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8505 # create TU dump
8506 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008507 if($UserLang eq "C") {
8508 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8509 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008510 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008511 or $MinGWMode{$Version}==1) {
8512 $TUdump .= " -fpreprocessed";
8513 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008514 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008515 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8516 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008517 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008518 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008519 if($?)
8520 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008521 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008522 { # try to recompile
8523 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008524 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008525 and index($Errors, "c99_")!=-1
8526 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008527 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008528 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008529
8530 if($Debug)
8531 {
8532 # printMsg("INFO", $Errors);
8533 }
8534
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008535 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008536 resetLogging($Version);
8537 $TMP_DIR = tempdir(CLEANUP=>1);
8538 return getDump();
8539 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008540 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008541 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008542 { # add auto preamble headers and try again
8543 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008544 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008545 foreach my $Num (0 .. $#Headers)
8546 {
8547 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008548 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8549 {
8550 push_U($Include_Preamble{$Version}, $Path);
8551 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008552 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008553 }
8554 resetLogging($Version);
8555 $TMP_DIR = tempdir(CLEANUP=>1);
8556 return getDump();
8557 }
8558 elsif($Cpp0xMode{$Version}!=-1
8559 and ($Errors=~/\Q-std=c++0x\E/
8560 or $Errors=~/is not a class or namespace/))
8561 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008562 if(check_gcc($GCC_PATH, "4.6"))
8563 {
8564 $Cpp0xMode{$Version}=-1;
8565 printMsg("INFO", "Enabling c++0x mode");
8566 resetLogging($Version);
8567 $TMP_DIR = tempdir(CLEANUP=>1);
8568 $CompilerOptions{$Version} .= " -std=c++0x";
8569 return getDump();
8570 }
8571 else {
8572 printMsg("WARNING", "Probably c++0x construction detected");
8573 }
8574
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008575 }
8576 elsif($MinGWMode{$Version}==1)
8577 { # disable MinGW mode and try again
8578 $MinGWMode{$Version}=-1;
8579 resetLogging($Version);
8580 $TMP_DIR = tempdir(CLEANUP=>1);
8581 return getDump();
8582 }
8583 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008584 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008585 else {
8586 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008588 printMsg("ERROR", "some errors occurred when compiling headers");
8589 printErrorLog($Version);
8590 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008591 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008592 }
8593 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008594 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008595 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008596
8597 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8598 return $TUs[0];
8599 }
8600 else
8601 {
8602 my $Msg = "can't compile header(s)";
8603 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8604 $Msg .= "\nDid you install G++?";
8605 }
8606 exitStatus("Cannot_Compile", $Msg);
8607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008608}
8609
8610sub cmd_file($)
8611{
8612 my $Path = $_[0];
8613 return "" if(not $Path or not -e $Path);
8614 if(my $CmdPath = get_CmdPath("file")) {
8615 return `$CmdPath -b \"$Path\"`;
8616 }
8617 return "";
8618}
8619
8620sub getIncString($$)
8621{
8622 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008623 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008624 my $String = "";
8625 foreach (@{$ArrRef}) {
8626 $String .= " ".inc_opt($_, $Style);
8627 }
8628 return $String;
8629}
8630
8631sub getIncPaths(@)
8632{
8633 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008634 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008635 if($INC_PATH_AUTODETECT{$Version})
8636 { # auto-detecting dependencies
8637 my %Includes = ();
8638 foreach my $HPath (@HeaderPaths)
8639 {
8640 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8641 {
8642 if($Skip_Include_Paths{$Version}{$Dir}) {
8643 next;
8644 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008645 if($SystemRoot)
8646 {
8647 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8648 next;
8649 }
8650 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008651 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008652 }
8653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008654 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008655 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008656 }
8657 }
8658 else
8659 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008660 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 }
8662 return \@IncPaths;
8663}
8664
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008665sub push_U($@)
8666{ # push unique
8667 if(my $Array = shift @_)
8668 {
8669 if(@_)
8670 {
8671 my %Exist = map {$_=>1} @{$Array};
8672 foreach my $Elem (@_)
8673 {
8674 if(not defined $Exist{$Elem})
8675 {
8676 push(@{$Array}, $Elem);
8677 $Exist{$Elem} = 1;
8678 }
8679 }
8680 }
8681 }
8682}
8683
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008684sub callPreprocessor($$$)
8685{
8686 my ($Path, $Inc, $LibVersion) = @_;
8687 return "" if(not $Path or not -f $Path);
8688 my $IncludeString=$Inc;
8689 if(not $Inc) {
8690 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8691 }
8692 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008693 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008694 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008695 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008696}
8697
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008698sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008699{ # native "find" is much faster than File::Find (~6x)
8700 # also the File::Find doesn't support --maxdepth N option
8701 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008702 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008703 return () if(not $Path or not -e $Path);
8704 if($OSgroup eq "windows")
8705 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008706 $Path = get_abs_path($Path);
8707 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008708 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008709 if($MaxDepth!=1) {
8710 $Cmd .= " /S";
8711 }
8712 if($Type eq "d") {
8713 $Cmd .= " /AD";
8714 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008715 elsif($Type eq "f") {
8716 $Cmd .= " /A-D";
8717 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008718 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008719 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008720 {
8721 if(not $UseRegex)
8722 { # FIXME: how to search file names in MS shell?
8723 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008724 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008725 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008726 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008727 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008728 }
8729 my @AbsPaths = ();
8730 foreach my $File (@Files)
8731 {
8732 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008733 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008734 }
8735 if($Type eq "f" and not -f $File)
8736 { # skip dirs
8737 next;
8738 }
8739 push(@AbsPaths, path_format($File, $OSgroup));
8740 }
8741 if($Type eq "d") {
8742 push(@AbsPaths, $Path);
8743 }
8744 return @AbsPaths;
8745 }
8746 else
8747 {
8748 my $FindCmd = get_CmdPath("find");
8749 if(not $FindCmd) {
8750 exitStatus("Not_Found", "can't find a \"find\" command");
8751 }
8752 $Path = get_abs_path($Path);
8753 if(-d $Path and -l $Path
8754 and $Path!~/\/\Z/)
8755 { # for directories that are symlinks
8756 $Path.="/";
8757 }
8758 my $Cmd = $FindCmd." \"$Path\"";
8759 if($MaxDepth) {
8760 $Cmd .= " -maxdepth $MaxDepth";
8761 }
8762 if($Type) {
8763 $Cmd .= " -type $Type";
8764 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008765 if($Name and not $UseRegex)
8766 { # wildcards
8767 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008768 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008769 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008770 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008771 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8772 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008773 my @Files = split(/\n/, $Res);
8774 if($Name and $UseRegex)
8775 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008776 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008777 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008778 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008779 }
8780}
8781
8782sub unpackDump($)
8783{
8784 my $Path = $_[0];
8785 return "" if(not $Path or not -e $Path);
8786 $Path = get_abs_path($Path);
8787 $Path = path_format($Path, $OSgroup);
8788 my ($Dir, $FileName) = separate_path($Path);
8789 my $UnpackDir = $TMP_DIR."/unpack";
8790 rmtree($UnpackDir);
8791 mkpath($UnpackDir);
8792 if($FileName=~s/\Q.zip\E\Z//g)
8793 { # *.zip
8794 my $UnzipCmd = get_CmdPath("unzip");
8795 if(not $UnzipCmd) {
8796 exitStatus("Not_Found", "can't find \"unzip\" command");
8797 }
8798 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008799 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008801 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008802 }
8803 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008804 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008805 if(not @Contents) {
8806 exitStatus("Error", "can't extract \'$Path\'");
8807 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008808 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008809 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008810 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008812 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 if($OSgroup eq "windows")
8814 { # -xvzf option is not implemented in tar.exe (2003)
8815 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8816 my $TarCmd = get_CmdPath("tar");
8817 if(not $TarCmd) {
8818 exitStatus("Not_Found", "can't find \"tar\" command");
8819 }
8820 my $GzipCmd = get_CmdPath("gzip");
8821 if(not $GzipCmd) {
8822 exitStatus("Not_Found", "can't find \"gzip\" command");
8823 }
8824 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008825 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008826 if($?) {
8827 exitStatus("Error", "can't extract \'$Path\'");
8828 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008829 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008830 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008831 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 }
8833 chdir($ORIG_DIR);
8834 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008835 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008836 if(not @Contents) {
8837 exitStatus("Error", "can't extract \'$Path\'");
8838 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008839 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008840 }
8841 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008842 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008843 my $TarCmd = get_CmdPath("tar");
8844 if(not $TarCmd) {
8845 exitStatus("Not_Found", "can't find \"tar\" command");
8846 }
8847 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008848 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008849 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008850 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008851 }
8852 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008853 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008854 if(not @Contents) {
8855 exitStatus("Error", "can't extract \'$Path\'");
8856 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008857 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008858 }
8859 }
8860}
8861
8862sub createArchive($$)
8863{
8864 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008865 if(not $To) {
8866 $To = ".";
8867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008868 if(not $Path or not -e $Path
8869 or not -d $To) {
8870 return "";
8871 }
8872 my ($From, $Name) = separate_path($Path);
8873 if($OSgroup eq "windows")
8874 { # *.zip
8875 my $ZipCmd = get_CmdPath("zip");
8876 if(not $ZipCmd) {
8877 exitStatus("Not_Found", "can't find \"zip\"");
8878 }
8879 my $Pkg = $To."/".$Name.".zip";
8880 unlink($Pkg);
8881 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008882 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008883 if($?)
8884 { # cannot allocate memory (or other problems with "zip")
8885 unlink($Path);
8886 exitStatus("Error", "can't pack the ABI dump: ".$!);
8887 }
8888 chdir($ORIG_DIR);
8889 unlink($Path);
8890 return $Pkg;
8891 }
8892 else
8893 { # *.tar.gz
8894 my $TarCmd = get_CmdPath("tar");
8895 if(not $TarCmd) {
8896 exitStatus("Not_Found", "can't find \"tar\"");
8897 }
8898 my $GzipCmd = get_CmdPath("gzip");
8899 if(not $GzipCmd) {
8900 exitStatus("Not_Found", "can't find \"gzip\"");
8901 }
8902 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8903 unlink($Pkg);
8904 chdir($From);
8905 system($TarCmd, "-czf", $Pkg, $Name);
8906 if($?)
8907 { # cannot allocate memory (or other problems with "tar")
8908 unlink($Path);
8909 exitStatus("Error", "can't pack the ABI dump: ".$!);
8910 }
8911 chdir($ORIG_DIR);
8912 unlink($Path);
8913 return $To."/".$Name.".tar.gz";
8914 }
8915}
8916
8917sub is_header_file($)
8918{
8919 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8920 return $_[0];
8921 }
8922 return 0;
8923}
8924
8925sub is_not_header($)
8926{
8927 if($_[0]=~/\.\w+\Z/
8928 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8929 return 1;
8930 }
8931 return 0;
8932}
8933
8934sub is_header($$$)
8935{
8936 my ($Header, $UserDefined, $LibVersion) = @_;
8937 return 0 if(-d $Header);
8938 if(-f $Header) {
8939 $Header = get_abs_path($Header);
8940 }
8941 else
8942 {
8943 if(is_abs($Header))
8944 { # incorrect absolute path
8945 return 0;
8946 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008947 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008948 $Header = $HPath;
8949 }
8950 else
8951 { # can't find header
8952 return 0;
8953 }
8954 }
8955 if($Header=~/\.\w+\Z/)
8956 { # have an extension
8957 return is_header_file($Header);
8958 }
8959 else
8960 {
8961 if($UserDefined==2)
8962 { # specified on the command line
8963 if(cmd_file($Header)!~/HTML|XML/i) {
8964 return $Header;
8965 }
8966 }
8967 elsif($UserDefined)
8968 { # specified in the XML-descriptor
8969 # header file without an extension
8970 return $Header;
8971 }
8972 else
8973 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008974 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008975 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008976 { # !~/HTML|XML|shared|dynamic/i
8977 return $Header;
8978 }
8979 }
8980 }
8981 return 0;
8982}
8983
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008984sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008985{
8986 my $LibVersion = $_[0];
8987 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8988 {
8989 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008990 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008991
8992 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8993 detect_recursive_includes($RegHeader, $LibVersion);
8994 }
8995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008996 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8997 {
8998 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008999
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009000 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009001 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9002 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009003 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009004 }
9005 }
9006 }
9007}
9008
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009009sub familiarDirs($$)
9010{
9011 my ($D1, $D2) = @_;
9012 if($D1 eq $D2) {
9013 return 1;
9014 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009015
9016 my $U1 = index($D1, "/usr/");
9017 my $U2 = index($D2, "/usr/");
9018
9019 if($U1==0 and $U2!=0) {
9020 return 0;
9021 }
9022
9023 if($U2==0 and $U1!=0) {
9024 return 0;
9025 }
9026
9027 if(index($D2, $D1."/")==0) {
9028 return 1;
9029 }
9030
9031 # /usr/include/DIR
9032 # /home/user/DIR
9033
9034 my $DL = get_depth($D1);
9035
9036 my @Dirs1 = ($D1);
9037 while($DL - get_depth($D1)<=2
9038 and get_depth($D1)>=4
9039 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9040 push(@Dirs1, $D1);
9041 }
9042
9043 my @Dirs2 = ($D2);
9044 while(get_depth($D2)>=4
9045 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9046 push(@Dirs2, $D2);
9047 }
9048
9049 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009050 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009051 foreach my $P2 (@Dirs2)
9052 {
9053
9054 if($P1 eq $P2) {
9055 return 1;
9056 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009057 }
9058 }
9059 return 0;
9060}
9061
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009062sub readHeaders($)
9063{
9064 $Version = $_[0];
9065 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9066 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009067 if($Debug)
9068 { # debug mode
9069 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009070 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009071 }
9072 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009073}
9074
9075sub prepareTypes($)
9076{
9077 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009078 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009079 { # support for old ABI dumps
9080 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009081 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009082 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009083 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9084 if($TName=~/\A(\w+)::(\w+)/) {
9085 my ($P1, $P2) = ($1, $2);
9086 if($P1 eq $P2) {
9087 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009089 else {
9090 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009092 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009093 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009094 }
9095 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009096 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009097 { # support for old ABI dumps
9098 # V < 2.5: array size == "number of elements"
9099 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009100 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009101 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009102 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009103 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009104 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009105 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009106 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009107 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009108 $Size *= $Base{"Size"};
9109 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009110 }
9111 else
9112 { # array[] is a pointer
9113 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009114 }
9115 }
9116 }
9117 }
9118 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009119 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009120 { # support for old ABI dumps
9121 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009122 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009123 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009124 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009125 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009127 my %Type = get_Type($TypeId, $LibVersion);
9128 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9129 my %Type2 = get_Type($TypeId_2, $V2);
9130 if($Type{"Size"} ne $Type2{"Size"}) {
9131 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009132 }
9133 }
9134 }
9135 }
9136}
9137
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009138sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009139{
9140 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009141
9142 if(not keys(%{$SymbolInfo{$LibVersion}}))
9143 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009144 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009145 {
9146 if($CheckHeadersOnly) {
9147 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9148 }
9149 else {
9150 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9151 }
9152 }
9153 }
9154
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009155 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009156 if(not checkDump(1, "2.10")
9157 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009158 { # different formats
9159 $Remangle = 1;
9160 }
9161 if($CheckHeadersOnly)
9162 { # different languages
9163 if($UserLang)
9164 { # --lang=LANG for both versions
9165 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9166 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9167 {
9168 if($UserLang eq "C++")
9169 { # remangle symbols
9170 $Remangle = 1;
9171 }
9172 elsif($UserLang eq "C")
9173 { # remove mangling
9174 $Remangle = -1;
9175 }
9176 }
9177 }
9178 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009179
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009180 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009182 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009183 { # support for old ABI dumps
9184 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9185 {
9186 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9187 {
9188 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9189 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009190 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009191 if(defined $DVal and $DVal ne "")
9192 {
9193 if($TName eq "char") {
9194 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9195 }
9196 elsif($TName eq "bool") {
9197 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9198 }
9199 }
9200 }
9201 }
9202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009203 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009204 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009205 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9206 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009207 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009208 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9209 # + support for old ABI dumps
9210 next;
9211 }
9212 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009213 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009214 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009215 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009216 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009217
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009218 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009219 if(not checkDump(1, "2.12")
9220 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009221 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009222 if($ShortName eq "operator>>")
9223 {
9224 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9225 { # corrected mangling of operator>>
9226 $SRemangle = 1;
9227 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009229 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9230 {
9231 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9232 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9233 { # corrected mangling of const global data
9234 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9235 # and incorrectly mangled by old ACC versions
9236 $SRemangle = 1;
9237 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009238 }
9239 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009240 if(not $CheckHeadersOnly)
9241 { # support for old ABI dumps
9242 if(not checkDump(1, "2.17")
9243 or not checkDump(2, "2.17"))
9244 {
9245 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9246 {
9247 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9248 {
9249 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9250 {
9251 $MnglName = $ShortName;
9252 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9253 }
9254 }
9255 }
9256 }
9257 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009258 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009259 { # support for old ABI dumps: some symbols are not mangled in old dumps
9260 # mangle both sets of symbols (old and new)
9261 # NOTE: remangling all symbols by the same mangler
9262 if($MnglName=~/\A_ZN(V|)K/)
9263 { # mangling may be incorrect on old ABI dumps
9264 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009265 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009266 }
9267 if($MnglName=~/\A_ZN(K|)V/)
9268 { # mangling may be incorrect on old ABI dumps
9269 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009270 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009271 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009272 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9273 or (not $ClassID and $CheckHeadersOnly)
9274 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9275 { # support for old ABI dumps, GCC >= 4.0
9276 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009277 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009278 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009279 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009280 $MangledNames{$LibVersion}{$MnglName} = 1;
9281 }
9282 }
9283 }
9284 elsif($Remangle==-1)
9285 { # remove mangling
9286 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009287 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 if(not $MnglName) {
9290 next;
9291 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009292
9293 # NOTE: duplicated entries in the ABI Dump
9294 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9295 {
9296 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9297 {
9298 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9299 {
9300 next;
9301 }
9302 }
9303 }
9304
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009305 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9306 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009307 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009309 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009310 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009311 { # support for old dumps
9312 # add "Volatile" attribute
9313 if($MnglName=~/_Z(K|)V/) {
9314 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9315 }
9316 }
9317 # symbol and its symlink have same signatures
9318 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009319 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009320 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009321
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009322 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9323 {
9324 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009325
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009326 if($SymVer{$LibVersion}{$Alias}) {
9327 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9328 }
9329 }
9330
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009331 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009332 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 }
9334 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9335 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9336 }
9337 if($ExtendedCheck)
9338 { # --ext option
9339 addExtension($LibVersion);
9340 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009341
9342 # clean memory
9343 delete($SymbolInfo{$LibVersion});
9344
9345 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 { # detect allocable classes with public exported constructors
9347 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009348 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009349 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009350 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009351 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009352 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9353 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009354 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009355 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009356 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009357 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009358 $AllocableClass{$LibVersion}{$ClassName} = 1;
9359 }
9360 }
9361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009362 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009363 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009364 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009365 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009366 if($CheckHeadersOnly)
9367 {
9368 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9369 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9370 { # all symbols except non-virtual inline
9371 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9372 }
9373 }
9374 else {
9375 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 }
9377 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009378 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009379 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009380 }
9381 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009382 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009383 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009384 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009386 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009387 if(defined $Base{"Type"}
9388 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009389 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009390 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009391 if($Name=~/<([^<>\s]+)>/)
9392 {
9393 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9394 $ReturnedClass{$LibVersion}{$Tid} = 1;
9395 }
9396 }
9397 else {
9398 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9399 }
9400 }
9401 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009402 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009403 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009404 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009405 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009407 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009409 if($Base{"Type"}=~/Struct|Class/)
9410 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009411 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009412 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9413 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009414 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 }
9417 }
9418 }
9419 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009420
9421 # mapping {short name => symbols}
9422 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009423 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009424 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009425 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009426 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009427 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009428 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009430 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9431 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009432 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009433 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009434 }
9435 }
9436 }
9437 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009438
9439 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009440 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009442 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009444 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9445 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009447 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009448 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009449 $ClassNames{$LibVersion}{$TName} = 1;
9450 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009452 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9453 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009454 }
9455 }
9456 }
9457 }
9458 }
9459}
9460
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009461sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009462{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009463 my ($Tid, $LibVersion) = @_;
9464 if(not $Tid) {
9465 return $Tid;
9466 }
9467
9468 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9469 {
9470 if($TName_Tid{$LibVersion}{$Name}) {
9471 return $TName_Tid{$LibVersion}{$Name};
9472 }
9473 }
9474
9475 return $Tid;
9476}
9477
9478sub register_SymbolUsage($$$)
9479{
9480 my ($InfoId, $UsedType, $LibVersion) = @_;
9481
9482 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9483 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9484 {
9485 register_TypeUsage($RTid, $UsedType, $LibVersion);
9486 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9487 }
9488 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9489 {
9490 register_TypeUsage($FCid, $UsedType, $LibVersion);
9491 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9492
9493 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9494 { # register "this" pointer
9495 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9496 }
9497 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9498 { # register "this" pointer (const method)
9499 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9500 }
9501 }
9502 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9503 {
9504 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9505 {
9506 register_TypeUsage($PTid, $UsedType, $LibVersion);
9507 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9508 }
9509 }
9510 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9511 {
9512 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9513 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9514 register_TypeUsage($TTid, $UsedType, $LibVersion);
9515 }
9516 }
9517}
9518
9519sub register_TypeUsage($$$)
9520{
9521 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009522 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009523 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009524 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009525 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009526 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009527 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009528 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009529
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009530 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009531 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009532 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009533 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009534 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009535 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9536 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9537 }
9538 }
9539
9540 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9541 {
9542 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009543 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009544 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009545 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9546 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009547 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009548 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9549 {
9550 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9551 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009552 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009553 }
9554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009555 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009556 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009557 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009558 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9559 {
9560 register_TypeUsage($MTid, $UsedType, $LibVersion);
9561 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009562 }
9563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009564 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009565 or $TInfo{"Type"} eq "MethodPtr"
9566 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009567 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009568 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009569 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009570 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009571 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009572 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009573 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9574 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009575 }
9576 }
9577 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009578 if($TInfo{"Type"} eq "FieldPtr")
9579 {
9580 if(my $RTid = $TInfo{"Return"}) {
9581 register_TypeUsage($RTid, $UsedType, $LibVersion);
9582 }
9583 if(my $CTid = $TInfo{"Class"}) {
9584 register_TypeUsage($CTid, $UsedType, $LibVersion);
9585 }
9586 }
9587 if($TInfo{"Type"} eq "MethodPtr")
9588 {
9589 if(my $CTid = $TInfo{"Class"}) {
9590 register_TypeUsage($CTid, $UsedType, $LibVersion);
9591 }
9592 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009593 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009594 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009595 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009596 $UsedType->{$TypeId} = 1;
9597 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9598 {
9599 register_TypeUsage($BTid, $UsedType, $LibVersion);
9600 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9601 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009602 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009603 else
9604 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9605 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009606 }
9607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009608}
9609
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009610sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009611{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009612 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9613
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009614 if($Level eq "Dump")
9615 {
9616 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9617 { # TODO: check if this symbol is from
9618 # base classes of other target symbols
9619 return 1;
9620 }
9621 }
9622
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009623 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9624 { # stdc++ interfaces
9625 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009626 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009627
9628 my $Target = 0;
9629 if(my $Header = $SInfo->{"Header"}) {
9630 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9631 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009632 if($ExtendedCheck)
9633 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009634 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009635 $Target = 1;
9636 }
9637 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009638 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009639 {
9640 if($Target)
9641 {
9642 if($Level eq "Dump")
9643 { # dumped
9644 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009645 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009646 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009647 return 1;
9648 }
9649 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009650 else {
9651 return 1;
9652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009653 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009654 elsif($Level eq "Source")
9655 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009656 return 1;
9657 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009658 elsif($Level eq "Binary")
9659 { # checked
9660 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9661 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9662 return 1;
9663 }
9664 }
9665 }
9666 }
9667 else
9668 { # library is available
9669 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9670 { # exported symbols
9671 return 1;
9672 }
9673 if($Level eq "Dump")
9674 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009675 if($BinaryOnly)
9676 {
9677 if($SInfo->{"Data"})
9678 {
9679 if($Target) {
9680 return 1;
9681 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009682 }
9683 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009684 else
9685 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009686 if($Target) {
9687 return 1;
9688 }
9689 }
9690 }
9691 elsif($Level eq "Source")
9692 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009693 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009694 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009695 { # skip LOCAL symbols
9696 if($Target) {
9697 return 1;
9698 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009699 }
9700 }
9701 elsif($Level eq "Binary")
9702 { # checked
9703 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9704 {
9705 if($Target) {
9706 return 1;
9707 }
9708 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009709 }
9710 }
9711 return 0;
9712}
9713
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714sub cleanDump($)
9715{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009716 my $LibVersion = $_[0];
9717 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9718 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009719 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9720 {
9721 delete($SymbolInfo{$LibVersion}{$InfoId});
9722 next;
9723 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009724 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009725 if(not $MnglName)
9726 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009727 delete($SymbolInfo{$LibVersion}{$InfoId});
9728 next;
9729 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009730 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009731 if(not $ShortName)
9732 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009733 delete($SymbolInfo{$LibVersion}{$InfoId});
9734 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009735 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009736 if($MnglName eq $ShortName)
9737 { # remove duplicate data
9738 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009739 }
9740 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9741 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9742 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009743 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9744 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9745 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009746 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009748 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009749 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009750 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9751 {
9752 delete($TypeInfo{$LibVersion}{$Tid});
9753 next;
9754 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009755 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009756 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009757 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009758 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9759 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9760 }
9761 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009762 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9763 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9764 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009765 }
9766}
9767
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009768sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009769{
9770 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009771
9772 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9773 {
9774 if(defined $TypeInfo{$LibVersion}{$Dupl})
9775 {
9776 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9777 { # duplicate
9778 return 0;
9779 }
9780 }
9781 }
9782
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009783 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9784
9785 if(isBuiltIn($THeader)) {
9786 return 0;
9787 }
9788
9789 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9790 return 0;
9791 }
9792
9793 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9794 return 0;
9795 }
9796
9797 if(selfTypedef($Tid, $LibVersion)) {
9798 return 0;
9799 }
9800
9801 if(not isTargetType($Tid, $LibVersion)) {
9802 return 0;
9803 }
9804
9805 return 0;
9806}
9807
9808sub isTargetType($$)
9809{
9810 my ($Tid, $LibVersion) = @_;
9811
9812 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9813 { # derived
9814 return 1;
9815 }
9816
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009817 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009818 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009819 if(not is_target_header($THeader, $LibVersion))
9820 { # from target headers
9821 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009822 }
9823 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009824 else
9825 { # NOTE: if type is defined in source
9826 if($UsedDump{$LibVersion}{"Public"})
9827 {
9828 if(isPrivateABI($Tid, $LibVersion)) {
9829 return 0;
9830 }
9831 else {
9832 return 1;
9833 }
9834 }
9835 else {
9836 return 0;
9837 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009838 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009839
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009840 if($SkipInternalTypes)
9841 {
9842 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9843 {
9844 return 0;
9845 }
9846 }
9847
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009848 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009849}
9850
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009851sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009852{ # remove unused data types from the ABI dump
9853 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009854
9855 my %UsedType = ();
9856
9857 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009858 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009859 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009860 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009861 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009862 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009863 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009864 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009865 next;
9866 }
9867
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009868 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009869 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009870 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009871 {
9872 my %Tree = ();
9873 register_TypeUsage($Tid, \%Tree, $LibVersion);
9874
9875 my $Tmpl = 0;
9876 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9877 {
9878 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9879 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9880 {
9881 $Tmpl = 1;
9882 last;
9883 }
9884 }
9885 if(not $Tmpl)
9886 {
9887 foreach (keys(%Tree)) {
9888 $UsedType{$_} = 1;
9889 }
9890 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009891 }
9892 }
9893 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009894
9895 my %Delete = ();
9896
9897 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009898 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009899 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009900 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009901 next;
9902 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009903
9904 if($Kind eq "Extra")
9905 {
9906 my %Tree = ();
9907 register_TypeUsage($Tid, \%Tree, $LibVersion);
9908
9909 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9910 {
9911 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9912 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9913 {
9914 $Delete{$Tid} = 1;
9915 last;
9916 }
9917 }
9918 }
9919 else
9920 {
9921 # remove type
9922 delete($TypeInfo{$LibVersion}{$Tid});
9923 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009924 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009925
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009926 if($Kind eq "Extra")
9927 { # remove duplicates
9928 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9929 {
9930 if($UsedType{$Tid})
9931 { # All & Extended
9932 next;
9933 }
9934
9935 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9936
9937 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9938 delete($TypeInfo{$LibVersion}{$Tid});
9939 }
9940 }
9941 }
9942
9943 foreach my $Tid (keys(%Delete))
9944 {
9945 delete($TypeInfo{$LibVersion}{$Tid});
9946 }
9947}
9948
9949sub check_Completeness($$)
9950{
9951 my ($Info, $LibVersion) = @_;
9952
9953 # data types
9954 if(defined $Info->{"Memb"})
9955 {
9956 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9957 {
9958 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9959 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9960 }
9961 }
9962 }
9963 if(defined $Info->{"Base"})
9964 {
9965 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9966 check_TypeInfo($Bid, $LibVersion);
9967 }
9968 }
9969 if(defined $Info->{"BaseType"}) {
9970 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9971 }
9972 if(defined $Info->{"TParam"})
9973 {
9974 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9975 {
9976 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9977 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9978 next;
9979 }
9980 if($TName eq "_BoolType") {
9981 next;
9982 }
9983 if($TName=~/\Asizeof\(/) {
9984 next;
9985 }
9986 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9987 check_TypeInfo($Tid, $LibVersion);
9988 }
9989 else
9990 {
9991 if(defined $Debug) {
9992 printMsg("WARNING", "missed type $TName");
9993 }
9994 }
9995 }
9996 }
9997
9998 # symbols
9999 if(defined $Info->{"Param"})
10000 {
10001 foreach my $Pos (keys(%{$Info->{"Param"}}))
10002 {
10003 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10004 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10005 }
10006 }
10007 }
10008 if(defined $Info->{"Return"}) {
10009 check_TypeInfo($Info->{"Return"}, $LibVersion);
10010 }
10011 if(defined $Info->{"Class"}) {
10012 check_TypeInfo($Info->{"Class"}, $LibVersion);
10013 }
10014}
10015
10016sub check_TypeInfo($$)
10017{
10018 my ($Tid, $LibVersion) = @_;
10019
10020 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10021 return;
10022 }
10023 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10024
10025 if(defined $TypeInfo{$LibVersion}{$Tid})
10026 {
10027 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10028 printMsg("ERROR", "missed type name ($Tid)");
10029 }
10030 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10031 }
10032 else {
10033 printMsg("ERROR", "missed type id $Tid");
10034 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010035}
10036
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010037sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010038{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010039 my ($TypeId, $LibVersion) = @_;
10040 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010041 if($Type{"Type"} eq "Typedef")
10042 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010043 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010044 if($Base{"Type"}=~/Class|Struct/)
10045 {
10046 if($Type{"Name"} eq $Base{"Name"}) {
10047 return 1;
10048 }
10049 elsif($Type{"Name"}=~/::(\w+)\Z/)
10050 {
10051 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10052 { # QPointer<QWidget>::QPointer
10053 return 1;
10054 }
10055 }
10056 }
10057 }
10058 return 0;
10059}
10060
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010061sub addExtension($)
10062{
10063 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010064 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010065 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010066 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010067 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010068 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10069 $TName=~s/\A(struct|union|class|enum) //;
10070 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010071
10072 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10073 "Header" => "extended.h",
10074 "ShortName" => $Symbol,
10075 "MnglName" => $Symbol,
10076 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10077 );
10078
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010079 $ExtendedSymbols{$Symbol} = 1;
10080 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10081 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010082 }
10083 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010084 $ExtendedSymbols{"external_func_0"} = 1;
10085 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10086 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010087}
10088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010089sub findMethod($$$)
10090{
10091 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010092 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010093 {
10094 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10095 return $VirtMethodInClass;
10096 }
10097 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10098 return $VirtMethodInBaseClasses;
10099 }
10100 }
10101 return "";
10102}
10103
10104sub findMethod_Class($$$)
10105{
10106 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010107 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010108 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10109 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10110 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10111 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10112 { # search for interface with the same parameters suffix (overridden)
10113 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10114 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010115 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10116 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010117 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10118 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010119 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10120 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10121 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10122 return $Candidate;
10123 }
10124 }
10125 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010126 else
10127 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010128 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10129 return $Candidate;
10130 }
10131 }
10132 }
10133 }
10134 return "";
10135}
10136
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010137sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010138{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010139 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010140 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010141 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010142 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10143 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010144 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010145 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010146 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010147 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10148 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010149 { # pure virtual D2-destructors are marked as "virt" in the dump
10150 # virtual D2-destructors are NOT marked as "virt" in the dump
10151 # both destructors are not presented in the v-table
10152 next;
10153 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010154 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010155 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010157 }
10158}
10159
10160sub registerOverriding($)
10161{
10162 my $LibVersion = $_[0];
10163 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010164 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010165 foreach my $ClassName (@Classes)
10166 {
10167 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10168 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010169 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10170 { # pure virtuals
10171 next;
10172 }
10173 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10174 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010175 {
10176 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10177 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10178 { # both overridden virtual methods
10179 # and implemented pure virtual methods
10180 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10181 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10182 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010184 }
10185 }
10186 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10187 delete($VirtualTable{$LibVersion}{$ClassName});
10188 }
10189 }
10190}
10191
10192sub setVirtFuncPositions($)
10193{
10194 my $LibVersion = $_[0];
10195 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10196 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010197 my ($Num, $Rel) = (1, 0);
10198
10199 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010200 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010201 if($UsedDump{$LibVersion}{"DWARF"}) {
10202 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10203 }
10204 else {
10205 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10206 }
10207 foreach my $VirtFunc (@Funcs)
10208 {
10209 if($UsedDump{$LibVersion}{"DWARF"}) {
10210 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10211 }
10212 else {
10213 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10214 }
10215
10216 # set relative positions
10217 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10218 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10219 { # relative position excluding added and removed virtual functions
10220 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10221 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10222 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010224 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010226 }
10227 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010228 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010229 {
10230 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010231 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010232 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010233 }
10234 }
10235}
10236
10237sub get_sub_classes($$$)
10238{
10239 my ($ClassId, $LibVersion, $Recursive) = @_;
10240 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10241 my @Subs = ();
10242 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10243 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010244 if($Recursive)
10245 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010246 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10247 push(@Subs, $SubSubId);
10248 }
10249 }
10250 push(@Subs, $SubId);
10251 }
10252 return @Subs;
10253}
10254
10255sub get_base_classes($$$)
10256{
10257 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010258 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010259 return () if(not defined $ClassType{"Base"});
10260 my @Bases = ();
10261 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10262 keys(%{$ClassType{"Base"}}))
10263 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010264 if($Recursive)
10265 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010266 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10267 push(@Bases, $SubBaseId);
10268 }
10269 }
10270 push(@Bases, $BaseId);
10271 }
10272 return @Bases;
10273}
10274
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010275sub getVTable_Model($$)
10276{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010277 my ($ClassId, $LibVersion) = @_;
10278 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10279 my @Elements = ();
10280 foreach my $BaseId (@Bases, $ClassId)
10281 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010282 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010283 {
10284 if(defined $VirtualTable{$LibVersion}{$BName})
10285 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010286 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10287 if($UsedDump{$LibVersion}{"DWARF"}) {
10288 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10289 }
10290 else {
10291 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10292 }
10293 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010294 push(@Elements, $VFunc);
10295 }
10296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010297 }
10298 }
10299 return @Elements;
10300}
10301
10302sub getVShift($$)
10303{
10304 my ($ClassId, $LibVersion) = @_;
10305 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10306 my $VShift = 0;
10307 foreach my $BaseId (@Bases)
10308 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010309 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010310 {
10311 if(defined $VirtualTable{$LibVersion}{$BName}) {
10312 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010314 }
10315 }
10316 return $VShift;
10317}
10318
10319sub getShift($$)
10320{
10321 my ($ClassId, $LibVersion) = @_;
10322 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10323 my $Shift = 0;
10324 foreach my $BaseId (@Bases)
10325 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010326 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010327 {
10328 if($Size!=1)
10329 { # not empty base class
10330 $Shift+=$Size;
10331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010332 }
10333 }
10334 return $Shift;
10335}
10336
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010337sub getVTable_Size($$)
10338{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010339 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010340 my $Size = 0;
10341 # three approaches
10342 if(not $Size)
10343 { # real size
10344 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10345 $Size = keys(%VTable);
10346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010347 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010348 if(not $Size)
10349 { # shared library symbol size
10350 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10351 $Size /= $WORD_SIZE{$LibVersion};
10352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010354 if(not $Size)
10355 { # model size
10356 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10357 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10358 }
10359 }
10360 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010361}
10362
10363sub isCopyingClass($$)
10364{
10365 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010366 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010367}
10368
10369sub isLeafClass($$)
10370{
10371 my ($ClassId, $LibVersion) = @_;
10372 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10373}
10374
10375sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010376{ # check structured type for public fields
10377 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010378}
10379
10380sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010381{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010382 my ($TypePtr, $Skip, $Start, $End) = @_;
10383 return 0 if(not $TypePtr);
10384 if($End==-1) {
10385 $End = keys(%{$TypePtr->{"Memb"}})-1;
10386 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010387 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010388 {
10389 if($Skip and $Skip->{$MemPos})
10390 { # skip removed/added fields
10391 next;
10392 }
10393 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10394 {
10395 if(isPublic($TypePtr, $MemPos)) {
10396 return ($MemPos+1);
10397 }
10398 }
10399 }
10400 return 0;
10401}
10402
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010403sub isReserved($)
10404{ # reserved fields == private
10405 my $MName = $_[0];
10406 if($MName=~/reserved|padding|f_spare/i) {
10407 return 1;
10408 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010409 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010410 return 1;
10411 }
10412 if($MName=~/(pad\d+)/i) {
10413 return 1;
10414 }
10415 return 0;
10416}
10417
10418sub isPublic($$)
10419{
10420 my ($TypePtr, $FieldPos) = @_;
10421 return 0 if(not $TypePtr);
10422 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10423 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10424 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10425 { # by name in C language
10426 # FIXME: add other methods to detect private members
10427 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10428 if($MName=~/priv|abidata|parent_object/i)
10429 { # C-styled private data
10430 return 0;
10431 }
10432 if(lc($MName) eq "abi")
10433 { # ABI information/reserved field
10434 return 0;
10435 }
10436 if(isReserved($MName))
10437 { # reserved fields
10438 return 0;
10439 }
10440 return 1;
10441 }
10442 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10443 { # by access in C++ language
10444 return 1;
10445 }
10446 return 0;
10447}
10448
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010449sub getVTable_Real($$)
10450{
10451 my ($ClassName, $LibVersion) = @_;
10452 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10453 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010454 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010455 if(defined $Type{"VTable"}) {
10456 return %{$Type{"VTable"}};
10457 }
10458 }
10459 return ();
10460}
10461
10462sub cmpVTables($)
10463{
10464 my $ClassName = $_[0];
10465 my $Res = cmpVTables_Real($ClassName, 1);
10466 if($Res==-1) {
10467 $Res = cmpVTables_Model($ClassName);
10468 }
10469 return $Res;
10470}
10471
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472sub cmpVTables_Model($)
10473{
10474 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010475 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010476 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010477 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010478 return 1;
10479 }
10480 }
10481 return 0;
10482}
10483
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010484sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010485{
10486 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10488 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010489 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 my %VTable_Old = getVTable_Real($ClassName, 1);
10491 my %VTable_New = getVTable_Real($ClassName, 2);
10492 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010493 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010494 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010495 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010496 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10498 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010501 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010502 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010503 my $Entry1 = $VTable_Old{$Offset};
10504 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010506 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010507 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010508 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510 $Entry1 = simpleVEntry($Entry1);
10511 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010512
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010513 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010514 { # NOTE: problem with vtable-dumper
10515 next;
10516 }
10517
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 if($Entry1 ne $Entry2)
10519 { # register as changed
10520 if($Entry1=~/::([^:]+)\Z/)
10521 {
10522 my $M1 = $1;
10523 if($Entry2=~/::([^:]+)\Z/)
10524 {
10525 my $M2 = $1;
10526 if($M1 eq $M2)
10527 { # overridden
10528 next;
10529 }
10530 }
10531 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010532 if(differentDumps("G"))
10533 {
10534 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10535 {
10536 # GCC 4.6.1: -0x00000000000000010
10537 # GCC 4.7.0: -16
10538 next;
10539 }
10540 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010541 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010542 }
10543 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010545}
10546
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010547sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010548{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010549 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010550 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10551 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010552 my $ClassId = $TName_Tid{1}{$ClassName};
10553 if(isPrivateABI($ClassId, 1)) {
10554 next;
10555 }
10556
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010557 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010558 { # already registered
10559 next;
10560 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010561 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010563 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010564 foreach my $Symbol (@Affected)
10565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010566 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010568 "Target"=>$ClassName);
10569 }
10570 }
10571 }
10572}
10573
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010574sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010576 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010577 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010579 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010580 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010581
10582 if(isPrivateABI($ClassId, 1)) {
10583 next;
10584 }
10585
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010586 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010588 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010589 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010590 if($TName_Tid{1}{$ClassName}
10591 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010592 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010593 if(defined $CompleteSignature{1}{$Symbol}
10594 and $CompleteSignature{1}{$Symbol}{"Virt"})
10595 { # override some method in v.1
10596 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010597 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010598 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 }
10600 }
10601 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010602 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010604 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010605 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010606 if($TName_Tid{2}{$ClassName}
10607 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010608 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 if(defined $CompleteSignature{2}{$Symbol}
10610 and $CompleteSignature{2}{$Symbol}{"Virt"})
10611 { # override some method in v.2
10612 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010613 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010614 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 }
10616 }
10617 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010618 if($Level eq "Binary")
10619 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010620 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010621 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10622 { # check replacements, including pure virtual methods
10623 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10624 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010626 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10627 if($AddedPos==$RemovedPos)
10628 {
10629 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10630 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10631 last; # other methods will be reported as "added" or "removed"
10632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010634 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10635 {
10636 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10637 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010638 next;
10639 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010640 my $ProblemType = "Virtual_Replacement";
10641 my @Affected = ($RemovedVFunc);
10642 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10643 { # pure methods
10644 if(not isUsedClass($ClassId, 1, $Level))
10645 { # not a parameter of some exported method
10646 next;
10647 }
10648 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010649
10650 # affected all methods (both virtual and non-virtual ones)
10651 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10652 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010654 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010655 foreach my $AffectedInt (@Affected)
10656 {
10657 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10658 { # affected exported methods only
10659 next;
10660 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010661 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10662 next;
10663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010664 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10665 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010666 "Target"=>get_Signature($AddedVFunc, 2),
10667 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669 }
10670 }
10671 }
10672 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010673 if(not checkDump(1, "2.0")
10674 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010675 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010676 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010677 return;
10678 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010679 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010680 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010681 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010682 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010683
10684 if(isPrivateABI($ClassId_Old, 1)) {
10685 next;
10686 }
10687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 if(not isCreatable($ClassId_Old, 1))
10689 { # skip classes without public constructors (including auto-generated)
10690 # example: class has only a private exported or private inline constructor
10691 next;
10692 }
10693 if($ClassName=~/>/)
10694 { # skip affected template instances
10695 next;
10696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010697 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010698 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010699 if(not $ClassId_New) {
10700 next;
10701 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010702 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010703 if($Class_New{"Type"}!~/Class|Struct/)
10704 { # became typedef
10705 if($Level eq "Binary") {
10706 next;
10707 }
10708 if($Level eq "Source")
10709 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010710 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010711 if($Class_New{"Type"}!~/Class|Struct/) {
10712 next;
10713 }
10714 $ClassId_New = $Class_New{"Tid"};
10715 }
10716 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010717
10718 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10719 { # incomplete info in the ABI dump
10720 next;
10721 }
10722
10723
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010724 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10725 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 +040010726
10727 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10728 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10729
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010730 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010731 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10732 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010733 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10734 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 my $Shift_Old = getShift($ClassId_Old, 1);
10736 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010737 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010738 my ($Added, $Removed) = (0, 0);
10739 my @StableBases_Old = ();
10740 foreach my $BaseId (@Bases_Old)
10741 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010742 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010743 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010744 push(@StableBases_Old, $BaseId);
10745 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010746 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010747 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010748 { # removed base
10749 # excluding namespace::SomeClass to SomeClass renaming
10750 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010751 if($Level eq "Binary")
10752 { # Binary-level
10753 if($Shift_Old ne $Shift_New)
10754 { # affected fields
10755 if(havePubFields(\%Class_Old)) {
10756 $ProblemKind .= "_And_Shift";
10757 }
10758 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10759 $ProblemKind .= "_And_Size";
10760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010761 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010762 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10763 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010764 { # affected v-table
10765 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010766 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010767 }
10768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010769 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010770 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10771 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010772 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10773 {
10774 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10775 if($ProblemKind=~/VTable/) {
10776 $VTableChanged_M{$SubName}=1;
10777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010778 }
10779 }
10780 foreach my $Interface (@Affected)
10781 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010782 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10783 next;
10784 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010785 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010786 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010787 "Target"=>$BaseName,
10788 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10789 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10790 "Shift"=>abs($Shift_New-$Shift_Old) );
10791 }
10792 $Removed+=1;
10793 }
10794 }
10795 my @StableBases_New = ();
10796 foreach my $BaseId (@Bases_New)
10797 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010798 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010799 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010800 push(@StableBases_New, $BaseId);
10801 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010802 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010803 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010804 { # added base
10805 # excluding namespace::SomeClass to SomeClass renaming
10806 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010807 if($Level eq "Binary")
10808 { # Binary-level
10809 if($Shift_Old ne $Shift_New)
10810 { # affected fields
10811 if(havePubFields(\%Class_Old)) {
10812 $ProblemKind .= "_And_Shift";
10813 }
10814 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10815 $ProblemKind .= "_And_Size";
10816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010817 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010818 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10819 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010820 { # affected v-table
10821 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010822 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 }
10824 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010825 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010826 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10827 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010828 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10829 {
10830 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10831 if($ProblemKind=~/VTable/) {
10832 $VTableChanged_M{$SubName}=1;
10833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 }
10835 }
10836 foreach my $Interface (@Affected)
10837 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010838 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10839 next;
10840 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010841 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010842 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010843 "Target"=>$BaseName,
10844 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10845 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10846 "Shift"=>abs($Shift_New-$Shift_Old) );
10847 }
10848 $Added+=1;
10849 }
10850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010851 if($Level eq "Binary")
10852 { # Binary-level
10853 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010854 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10855 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010856 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010857 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010858 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010859 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010860 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10862 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010863 if($NewPos!=$OldPos)
10864 { # changed position of the base class
10865 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010866 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010867 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10868 next;
10869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010870 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10871 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010872 "Target"=>$BaseName,
10873 "Old_Value"=>$OldPos-1,
10874 "New_Value"=>$NewPos-1 );
10875 }
10876 }
10877 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10878 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10879 { # became non-virtual base
10880 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10881 {
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_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10886 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010887 "Target"=>$BaseName );
10888 }
10889 }
10890 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10891 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10892 { # became virtual base
10893 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10894 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010895 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10896 next;
10897 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010898 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10899 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010900 "Target"=>$BaseName );
10901 }
10902 }
10903 }
10904 }
10905 # detect size changes in base classes
10906 if($Shift_Old!=$Shift_New)
10907 { # size of allocable class
10908 foreach my $BaseId (@StableBases_Old)
10909 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010910 my %BaseType = get_Type($BaseId, 1);
10911 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010912 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010913 if($Size_Old ne $Size_New
10914 and $Size_Old and $Size_New)
10915 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010916 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010917 if(isCopyingClass($BaseId, 1)) {
10918 $ProblemType = "Size_Of_Copying_Class";
10919 }
10920 elsif($AllocableClass{1}{$BaseType{"Name"}})
10921 {
10922 if($Size_New>$Size_Old)
10923 { # increased size
10924 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010926 else
10927 { # decreased size
10928 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10929 if(not havePubFields(\%Class_Old))
10930 { # affected class has no public members
10931 next;
10932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010934 }
10935 next if(not $ProblemType);
10936 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10937 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010938 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10939 next;
10940 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10942 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010943 "Target"=>$BaseType{"Name"},
10944 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10945 "New_Size"=>$Size_New*$BYTE_SIZE );
10946 }
10947 }
10948 }
10949 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010950 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010951 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010952 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 { # compare virtual tables size in base classes
10954 my $VShift_Old = getVShift($ClassId_Old, 1);
10955 my $VShift_New = getVShift($ClassId_New, 2);
10956 if($VShift_Old ne $VShift_New)
10957 { # changes in the base class or changes in the list of base classes
10958 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10959 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10960 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010961 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010962 foreach my $BaseId (@AllBases_Old)
10963 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010964 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010965 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 { # lost base
10967 next;
10968 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010969 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10970 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010971 if($VSize_Old!=$VSize_New)
10972 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010973 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010974 { # TODO: affected non-virtual methods?
10975 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10977 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010978 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010979 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010980 { # skip interfaces that have not changed the absolute virtual position
10981 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010982 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010983 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10984 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010985 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010986 $VTableChanged_M{$BaseType{"Name"}} = 1;
10987 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010988 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10989 { # the reason of the layout change: added virtual functions
10990 next if($VirtualReplacement{$VirtFunc});
10991 my $ProblemType = "Added_Virtual_Method";
10992 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10993 $ProblemType = "Added_Pure_Virtual_Method";
10994 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010995 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010997 "Target"=>get_Signature($VirtFunc, 2) );
10998 }
10999 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11000 { # the reason of the layout change: removed virtual functions
11001 next if($VirtualReplacement{$VirtFunc});
11002 my $ProblemType = "Removed_Virtual_Method";
11003 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11004 $ProblemType = "Removed_Pure_Virtual_Method";
11005 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011006 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011008 "Target"=>get_Signature($VirtFunc, 1) );
11009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011010 }
11011 }
11012 }
11013 }
11014 }
11015 }
11016 }
11017}
11018
11019sub isCreatable($$)
11020{
11021 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011022 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011023 or isCopyingClass($ClassId, $LibVersion)) {
11024 return 1;
11025 }
11026 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11027 { # Fix for incomplete data: if this class has
11028 # a base class then it should also has a constructor
11029 return 1;
11030 }
11031 if($ReturnedClass{$LibVersion}{$ClassId})
11032 { # returned by some method of this class
11033 # or any other class
11034 return 1;
11035 }
11036 return 0;
11037}
11038
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011039sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011040{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011041 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011042 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11043 { # parameter of some exported method
11044 return 1;
11045 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011046 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11047 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011048 { # method from target class
11049 return 1;
11050 }
11051 return 0;
11052}
11053
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011054sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011055{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011056 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011057 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011058 # - virtual
11059 # - pure-virtual
11060 # - non-virtual
11061 if($CompleteSignature{1}{$Interface}{"Data"})
11062 { # global data is not affected
11063 return;
11064 }
11065 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011066 if(not $Class_Id) {
11067 return;
11068 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011069 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011070 if(cmpVTables_Real($CName, 1)==0)
11071 { # no changes
11072 return;
11073 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011074 $CheckedTypes{$Level}{$CName} = 1;
11075 if($Level eq "Binary")
11076 { # Binary-level
11077 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11078 and not isUsedClass($Class_Id, 1, $Level))
11079 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011080 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011081 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011082 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011083 }
11084 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11085 {
11086 if(defined $VirtualTable{2}{$CName}{$Func}
11087 and defined $CompleteSignature{2}{$Func})
11088 {
11089 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11090 and $CompleteSignature{2}{$Func}{"PureVirt"})
11091 { # became pure virtual
11092 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11093 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011094 "Target"=>get_Signature_M($Func, 1) );
11095 $VTableChanged_M{$CName} = 1;
11096 }
11097 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11098 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11099 { # became non-pure virtual
11100 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11101 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011102 "Target"=>get_Signature_M($Func, 1) );
11103 $VTableChanged_M{$CName} = 1;
11104 }
11105 }
11106 }
11107 if($Level eq "Binary")
11108 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011109 # check virtual table structure
11110 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11111 {
11112 next if($Interface eq $AddedVFunc);
11113 next if($VirtualReplacement{$AddedVFunc});
11114 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11115 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11116 { # pure virtual methods affect all others (virtual and non-virtual)
11117 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011118 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011119 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011120 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011122 elsif(not defined $VirtualTable{1}{$CName}
11123 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011125 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011126 { # became polymorphous class, added v-table pointer
11127 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011128 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011130 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 }
11132 else
11133 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011134 my $VSize_Old = getVTable_Size($CName, 1);
11135 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011136 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 if(isCopyingClass($Class_Id, 1))
11138 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11139 my $ProblemType = "Added_Virtual_Method";
11140 if(isLeafClass($Class_Id, 1)) {
11141 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11142 }
11143 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11144 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011148 else
11149 {
11150 my $ProblemType = "Added_Virtual_Method";
11151 if(isLeafClass($Class_Id, 1)) {
11152 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11153 }
11154 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11155 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011156 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011157 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011159 }
11160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11162 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011163 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011164 if(defined $VirtualTable{1}{$CName}
11165 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011166 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011167 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11168 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011169
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011170 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011171 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011172 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11173 foreach my $ASymbol (@Affected)
11174 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011175 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11176 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011177 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011178 next;
11179 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011180 }
11181 $CheckedSymbols{$Level}{$ASymbol} = 1;
11182 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11183 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011184 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011185 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011188 }
11189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011190 else {
11191 # safe
11192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11195 {
11196 next if($VirtualReplacement{$RemovedVFunc});
11197 if($RemovedVFunc eq $Interface
11198 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11199 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011200 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011201 next;
11202 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011203 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011204 { # became non-polymorphous class, removed v-table pointer
11205 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11206 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011208 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011209 }
11210 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11211 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11212 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011213 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011214 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011215 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11216 next;
11217 }
11218 my $VPos_New = -1;
11219 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011220 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011221 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11222 }
11223 else
11224 {
11225 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 next;
11227 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011228 }
11229 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11230 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11231 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11232 {
11233 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11234 foreach my $ASymbol (@Affected)
11235 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011236 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11237 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011238 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011239 next;
11240 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011241 }
11242 my $ProblemType = "Removed_Virtual_Method";
11243 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11244 $ProblemType = "Removed_Pure_Virtual_Method";
11245 }
11246 $CheckedSymbols{$Level}{$ASymbol} = 1;
11247 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11248 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011249 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011250 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011252 }
11253 }
11254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011255 }
11256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011257 else
11258 { # Source-level
11259 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011261 next if($Interface eq $AddedVFunc);
11262 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011263 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011264 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11265 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011266 "Target"=>get_Signature($AddedVFunc, 2) );
11267 }
11268 }
11269 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11270 {
11271 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11272 {
11273 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11274 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 }
11277 }
11278 }
11279}
11280
11281sub find_MemberPair_Pos_byName($$)
11282{
11283 my ($Member_Name, $Pair_Type) = @_;
11284 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11285 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11286 {
11287 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11288 {
11289 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11290 $Name=~s/\A[_]+|[_]+\Z//g;
11291 if($Name eq $Member_Name) {
11292 return $MemberPair_Pos;
11293 }
11294 }
11295 }
11296 return "lost";
11297}
11298
11299sub find_MemberPair_Pos_byVal($$)
11300{
11301 my ($Member_Value, $Pair_Type) = @_;
11302 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11303 {
11304 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11305 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11306 return $MemberPair_Pos;
11307 }
11308 }
11309 return "lost";
11310}
11311
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011312sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011313{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011314 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011315 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011316 if( $_->{"T1"} eq $_[0]
11317 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011318 {
11319 return 1;
11320 }
11321 }
11322 return 0;
11323}
11324
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011325sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011326{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011327 my %IDs = (
11328 "T1" => $_[0],
11329 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011330 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011331 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011332}
11333
11334sub isRenamed($$$$$)
11335{
11336 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11337 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11338 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011339 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011340 if(not defined $Type2->{"Memb"}{$MemPos}) {
11341 return "";
11342 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011343 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011344 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011345
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011346 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11347 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011348 if($MemberPair_Pos_Rev eq "lost")
11349 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011350 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11351 { # base type match
11352 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011353 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011354 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11355 { # exact type match
11356 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011358 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11359 { # size match
11360 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011361 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011362 if(isReserved($Pair_Name))
11363 { # reserved fields
11364 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 }
11366 }
11367 return "";
11368}
11369
11370sub isLastElem($$)
11371{
11372 my ($Pos, $TypeRef) = @_;
11373 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11374 if($Name=~/last|count|max|total/i)
11375 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11376 return 1;
11377 }
11378 elsif($Name=~/END|NLIMITS\Z/)
11379 { # __RLIMIT_NLIMITS
11380 return 1;
11381 }
11382 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11383 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11384 { # NImageFormats, NColorRoles
11385 return 1;
11386 }
11387 return 0;
11388}
11389
11390sub nonComparable($$)
11391{
11392 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011393
11394 my $N1 = $T1->{"Name"};
11395 my $N2 = $T2->{"Name"};
11396
11397 $N1=~s/\A(struct|union|enum) //;
11398 $N2=~s/\A(struct|union|enum) //;
11399
11400 if($N1 ne $N2
11401 and not isAnon($N1)
11402 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011403 { # different names
11404 if($T1->{"Type"} ne "Pointer"
11405 or $T2->{"Type"} ne "Pointer")
11406 { # compare base types
11407 return 1;
11408 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011409 if($N1!~/\Avoid\s*\*/
11410 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011411 {
11412 return 1;
11413 }
11414 }
11415 elsif($T1->{"Type"} ne $T2->{"Type"})
11416 { # different types
11417 if($T1->{"Type"} eq "Class"
11418 and $T2->{"Type"} eq "Struct")
11419 { # "class" to "struct"
11420 return 0;
11421 }
11422 elsif($T2->{"Type"} eq "Class"
11423 and $T1->{"Type"} eq "Struct")
11424 { # "struct" to "class"
11425 return 0;
11426 }
11427 else
11428 { # "class" to "enum"
11429 # "union" to "class"
11430 # ...
11431 return 1;
11432 }
11433 }
11434 return 0;
11435}
11436
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011437sub isOpaque($)
11438{
11439 my $T = $_[0];
11440 if(not defined $T->{"Memb"})
11441 {
11442 return 1;
11443 }
11444 return 0;
11445}
11446
11447sub removeVPtr($)
11448{ # support for old ABI dumps
11449 my $TPtr = $_[0];
11450 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11451 if($#Pos>=1)
11452 {
11453 foreach my $Pos (0 .. $#Pos-1)
11454 {
11455 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11456 }
11457 delete($TPtr->{"Memb"}{$#Pos});
11458 }
11459}
11460
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011461sub isPrivateABI($$)
11462{
11463 my ($TypeId, $LibVersion) = @_;
11464
11465 if($CheckPrivateABI) {
11466 return 0;
11467 }
11468
11469 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11470 return 1;
11471 }
11472
11473 return 0;
11474}
11475
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011476sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011477{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011478 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011479 return {} if(not $Type1_Id or not $Type2_Id);
11480
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011481 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011482 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011483 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011484 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011485
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011486 my %Type1 = get_Type($Type1_Id, 1);
11487 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011488 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011489 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011490 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011491
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011492 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11493 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011494
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011495 if(defined $UsedDump{1}{"DWARF"})
11496 {
11497 if($Type1_Pure{"Name"} eq "__unknown__"
11498 or $Type2_Pure{"Name"} eq "__unknown__")
11499 { # Error ABI dump
11500 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11501 }
11502 }
11503
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011504 if(isPrivateABI($Type1_Id, 1)) {
11505 return {};
11506 }
11507
11508 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11509 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11510
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011511 my %SubProblems = ();
11512
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011513 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11514 {
11515 if($Type1_Pure{"Type"}=~/Struct|Union/
11516 and $Type2_Pure{"Type"}=~/Struct|Union/)
11517 {
11518 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11519 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011520 if(not defined $UsedDump{1}{"DWARF"}
11521 and not defined $UsedDump{2}{"DWARF"})
11522 {
11523 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11524 "Target"=>$Type1_Pure{"Name"},
11525 "Type_Name"=>$Type1_Pure{"Name"} );
11526 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011527
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011528 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011529 }
11530 }
11531 }
11532
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011533 if(not $Type1_Pure{"Size"}
11534 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011535 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011536 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11537 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11538 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011539 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011540 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011541 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011542 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011543 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011544 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011545 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011546 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11547 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11548 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011549
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011550 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11551 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011552 }
11553
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011554 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11555 { # support for old ABI dumps
11556 # _vptr field added in 3.0
11557 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11558 {
11559 if(defined $Type2_Pure{"Memb"}
11560 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11561 {
11562 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11563 delete($Type2_Pure{"Memb"}{0});
11564 }
11565 else {
11566 removeVPtr(\%Type2_Pure);
11567 }
11568 }
11569 }
11570 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11571 {
11572 if(defined $Type1_Pure{"Memb"}
11573 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11574 {
11575 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11576 delete($Type1_Pure{"Memb"}{0});
11577 }
11578 else {
11579 removeVPtr(\%Type1_Pure);
11580 }
11581 }
11582 }
11583 }
11584
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011585 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11586 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011587
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011588 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011589 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11590 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011591 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011592 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11593 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011594 if($Base_1{"Name"} ne $Base_2{"Name"})
11595 {
11596 if(differentDumps("G")
11597 or differentDumps("V"))
11598 { # different GCC versions or different dumps
11599 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11600 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11601 # std::__va_list and __va_list
11602 $Base_1{"Name"}=~s/\A(\w+::)+//;
11603 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011604 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11605 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011607 }
11608 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11609 and $Base_1{"Name"} ne $Base_2{"Name"})
11610 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011611 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011612 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011613 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011614 {
11615 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11616 "Target"=>$Typedef_1{"Name"},
11617 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011618 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11619 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11620 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011621 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11622 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011623
11624 if(defined $UsedDump{1}{"DWARF"})
11625 {
11626 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11627 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11628 { # Error ABI dump
11629 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11630 }
11631 }
11632
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011633 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011634 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011635 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11636 {
11637 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11638 "Target"=>$Typedef_1{"Name"},
11639 "Type_Name"=>$Typedef_1{"Name"},
11640 "Old_Value"=>$Base_1{"Name"},
11641 "New_Value"=>$Base_2{"Name"} );
11642 }
11643 else
11644 {
11645 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11646 "Target"=>$Typedef_1{"Name"},
11647 "Type_Name"=>$Typedef_1{"Name"},
11648 "Old_Value"=>$Base_1{"Name"},
11649 "New_Value"=>$Base_2{"Name"} );
11650 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011652 }
11653 }
11654 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11655 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011656 my $TT1 = $Type1_Pure{"Type"};
11657 my $TT2 = $Type2_Pure{"Type"};
11658
11659 if($TT1 ne $TT2
11660 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011661 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011662 my $Short1 = $Type1_Pure{"Name"};
11663 my $Short2 = $Type2_Pure{"Name"};
11664
11665 $Short1=~s/\A\Q$TT1\E //ig;
11666 $Short2=~s/\A\Q$TT2\E //ig;
11667
11668 if($Short1 eq $Short2)
11669 {
11670 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11671 "Target"=>$Type1_Pure{"Name"},
11672 "Type_Name"=>$Type1_Pure{"Name"},
11673 "Old_Value"=>lc($Type1_Pure{"Type"}),
11674 "New_Value"=>lc($Type2_Pure{"Type"}) );
11675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011676 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011677 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011678 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011679
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011680 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011681
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011682 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11683 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11684 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11685 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011686 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011687 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011688 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011689 {
11690 my $ProblemKind = "DataType_Size";
11691 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011692 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011693 {
11694 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11695 $ProblemKind = "Size_Of_Copying_Class";
11696 }
11697 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11698 {
11699 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11700 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11701 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011702 else
11703 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 # descreased size of allocable class
11705 # it has no special effects
11706 }
11707 }
11708 }
11709 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11710 "Target"=>$Type1_Pure{"Name"},
11711 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011712 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011713 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011714 }
11715 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011716 if(defined $Type1_Pure{"BaseType"}
11717 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011718 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011719 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11720 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011721 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011722 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11723 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011724 }
11725 }
11726 }
11727 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11728 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11729 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11730 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11731 { # detect removed and renamed fields
11732 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11733 next if(not $Member_Name);
11734 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);
11735 if($MemberPair_Pos eq "lost")
11736 {
11737 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11738 {
11739 if(isUnnamed($Member_Name))
11740 { # support for old-version dumps
11741 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011742 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011743 next;
11744 }
11745 }
11746 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11747 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011748 $RenamedField{$Member_Pos} = $RenamedTo;
11749 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011750 }
11751 else
11752 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011753 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 }
11755 }
11756 elsif($Type1_Pure{"Type"} eq "Enum")
11757 {
11758 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11759 next if($Member_Value1 eq "");
11760 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11761 if($MemberPair_Pos ne "lost")
11762 { # renamed
11763 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11764 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11765 if($MemberPair_Pos_Rev eq "lost")
11766 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011767 $RenamedField{$Member_Pos} = $RenamedTo;
11768 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011769 }
11770 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011771 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 }
11773 }
11774 else
11775 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011776 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011777 }
11778 }
11779 }
11780 else
11781 { # related
11782 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11783 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11784 }
11785 }
11786 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11787 { # detect added fields
11788 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11789 next if(not $Member_Name);
11790 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);
11791 if($MemberPair_Pos eq "lost")
11792 {
11793 if(isUnnamed($Member_Name))
11794 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011795 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011796 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011797 next;
11798 }
11799 }
11800 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11801 {
11802 if(not $RenamedField_Rev{$Member_Pos})
11803 { # added
11804 $AddedField{$Member_Pos}=1;
11805 }
11806 }
11807 }
11808 }
11809 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11810 { # detect moved fields
11811 my (%RelPos, %RelPosName, %AbsPos) = ();
11812 my $Pos = 0;
11813 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11814 { # relative positions in 1st version
11815 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11816 next if(not $Member_Name);
11817 if(not $RemovedField{$Member_Pos})
11818 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011819 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011820 $RelPosName{1}{$Pos} = $Member_Name;
11821 $AbsPos{1}{$Pos++} = $Member_Pos;
11822 }
11823 }
11824 $Pos = 0;
11825 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11826 { # relative positions in 2nd version
11827 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11828 next if(not $Member_Name);
11829 if(not $AddedField{$Member_Pos})
11830 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011831 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011832 $RelPosName{2}{$Pos} = $Member_Name;
11833 $AbsPos{2}{$Pos++} = $Member_Pos;
11834 }
11835 }
11836 foreach my $Member_Name (keys(%{$RelPos{1}}))
11837 {
11838 my $RPos1 = $RelPos{1}{$Member_Name};
11839 my $AbsPos1 = $NameToPosA{$Member_Name};
11840 my $Member_Name2 = $Member_Name;
11841 if(my $RenamedTo = $RenamedField{$AbsPos1})
11842 { # renamed
11843 $Member_Name2 = $RenamedTo;
11844 }
11845 my $RPos2 = $RelPos{2}{$Member_Name2};
11846 if($RPos2 ne "" and $RPos1 ne $RPos2)
11847 { # different relative positions
11848 my $AbsPos2 = $NameToPosB{$Member_Name2};
11849 if($AbsPos1 ne $AbsPos2)
11850 { # different absolute positions
11851 my $ProblemType = "Moved_Field";
11852 if(not isPublic(\%Type1_Pure, $AbsPos1))
11853 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011854 if($Level eq "Source") {
11855 next;
11856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011857 $ProblemType = "Moved_Private_Field";
11858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011859 if($Level eq "Binary"
11860 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011861 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011862 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011863 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011864 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011865 if($MemSize1 ne $MemSize2) {
11866 $ProblemType .= "_And_Size";
11867 }
11868 }
11869 if($ProblemType eq "Moved_Private_Field") {
11870 next;
11871 }
11872 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11873 "Target"=>$Member_Name,
11874 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011875 "Old_Value"=>$RPos1,
11876 "New_Value"=>$RPos2 );
11877 }
11878 }
11879 }
11880 }
11881 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011882 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011883 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11884 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011885 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011886 if(my $RenamedTo = $RenamedField{$Member_Pos})
11887 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011888 if(defined $Constants{2}{$Member_Name})
11889 {
11890 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11891 { # define OLD NEW
11892 next; # Safe
11893 }
11894 }
11895
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011896 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11897 {
11898 if(isPublic(\%Type1_Pure, $Member_Pos))
11899 {
11900 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11901 "Target"=>$Member_Name,
11902 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011903 "Old_Value"=>$Member_Name,
11904 "New_Value"=>$RenamedTo );
11905 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011906 elsif(isReserved($Member_Name))
11907 {
11908 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11909 "Target"=>$Member_Name,
11910 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011911 "Old_Value"=>$Member_Name,
11912 "New_Value"=>$RenamedTo );
11913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011914 }
11915 elsif($Type1_Pure{"Type"} eq "Enum")
11916 {
11917 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11918 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11919 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011920 "Old_Value"=>$Member_Name,
11921 "New_Value"=>$RenamedTo );
11922 }
11923 }
11924 elsif($RemovedField{$Member_Pos})
11925 { # removed
11926 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11927 {
11928 my $ProblemType = "Removed_Field";
11929 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011930 or isUnnamed($Member_Name))
11931 {
11932 if($Level eq "Source") {
11933 next;
11934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011935 $ProblemType = "Removed_Private_Field";
11936 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011937 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011938 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011939 {
11940 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11941 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011942 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 +040011943 { # changed offset
11944 $ProblemType .= "_And_Layout";
11945 }
11946 }
11947 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11948 { # affected size
11949 $ProblemType .= "_And_Size";
11950 }
11951 }
11952 if($ProblemType eq "Removed_Private_Field") {
11953 next;
11954 }
11955 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11956 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011957 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011958 }
11959 elsif($Type2_Pure{"Type"} eq "Union")
11960 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011961 if($Level eq "Binary"
11962 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011963 {
11964 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11965 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011966 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011967 }
11968 else
11969 {
11970 %{$SubProblems{"Removed_Union_Field"}{$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 }
11975 elsif($Type1_Pure{"Type"} eq "Enum")
11976 {
11977 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11978 "Target"=>$Member_Name,
11979 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011980 "Old_Value"=>$Member_Name );
11981 }
11982 }
11983 else
11984 { # changed
11985 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11986 if($Type1_Pure{"Type"} eq "Enum")
11987 {
11988 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11989 next if($Member_Value1 eq "");
11990 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11991 next if($Member_Value2 eq "");
11992 if($Member_Value1 ne $Member_Value2)
11993 {
11994 my $ProblemType = "Enum_Member_Value";
11995 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11996 $ProblemType = "Enum_Last_Member_Value";
11997 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011998 if($SkipConstants{1}{$Member_Name}) {
11999 $ProblemType = "Enum_Private_Member_Value";
12000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012001 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12002 "Target"=>$Member_Name,
12003 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 "Old_Value"=>$Member_Value1,
12005 "New_Value"=>$Member_Value2 );
12006 }
12007 }
12008 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12009 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012010 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12011 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12012
12013 if($Access1 ne "private"
12014 and $Access2 eq "private")
12015 {
12016 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12017 "Target"=>$Member_Name,
12018 "Type_Name"=>$Type1_Pure{"Name"});
12019 }
12020 elsif($Access1 ne "protected"
12021 and $Access1 ne "private"
12022 and $Access2 eq "protected")
12023 {
12024 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12025 "Target"=>$Member_Name,
12026 "Type_Name"=>$Type1_Pure{"Name"});
12027 }
12028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012029 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12030 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012031 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012032 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12033 $SizeV1 = $BSize1;
12034 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012035 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012036 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12037 $SizeV2 = $BSize2;
12038 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012039 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12040 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012041 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012042 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012043 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012044 {
12045 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12046 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12047 { # field size change (including anon-structures and unions)
12048 # - same types
12049 # - unnamed types
12050 # - bitfields
12051 my $ProblemType = "Field_Size";
12052 if(not isPublic(\%Type1_Pure, $Member_Pos)
12053 or isUnnamed($Member_Name))
12054 { # should not be accessed by applications, goes to "Low Severity"
12055 # example: "abidata" members in GStreamer types
12056 $ProblemType = "Private_".$ProblemType;
12057 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012058 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 +040012059 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012060 if($Type2_Pure{"Type"} ne "Union"
12061 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012062 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012063 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 +040012064 { # changed offset
12065 $ProblemType .= "_And_Layout";
12066 }
12067 }
12068 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12069 $ProblemType .= "_And_Type_Size";
12070 }
12071 }
12072 if($ProblemType eq "Private_Field_Size")
12073 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012075 if($ProblemType eq "Field_Size")
12076 {
12077 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12078 { # Low severity
12079 $ProblemType = "Struct_Field_Size_Increased";
12080 }
12081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012082 if($ProblemType)
12083 { # register a problem
12084 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12085 "Target"=>$Member_Name,
12086 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012087 "Old_Size"=>$SizeV1,
12088 "New_Size"=>$SizeV2);
12089 }
12090 }
12091 }
12092 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12093 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12094 { # do NOT check bitfield type changes
12095 next;
12096 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012097 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012098 {
12099 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12100 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12101 {
12102 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12103 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012104 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012105 }
12106 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12107 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12108 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012109 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012110 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012111 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012112 }
12113 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012114 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12115 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012116 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012117 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12118 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012119
12120 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012121 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012122 or $ProblemType eq "Field_Type_And_Size"
12123 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012125 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012126 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012127 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012128 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012129 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012130 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012131 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012132 }
12133 }
12134 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12135 {
12136 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012137 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012138 }
12139 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012140 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012141 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012142 }
12143 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12144 {
12145 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012146 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012147 }
12148 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012149 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012150 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012151 }
12152 }
12153 }
12154
12155 if($Level eq "Source")
12156 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012157 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012158 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012159 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12160 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012161
12162 if($ProblemType eq "Field_Type")
12163 {
12164 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012165 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012166 }
12167 }
12168 }
12169 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012170
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012171 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012172 {
12173 my $ProblemType_Init = $ProblemType;
12174 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012175 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012176 if(not isPublic(\%Type1_Pure, $Member_Pos)
12177 or isUnnamed($Member_Name)) {
12178 $ProblemType = "Private_".$ProblemType;
12179 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012180 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 +040012181 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012182 if($Type2_Pure{"Type"} ne "Union"
12183 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012184 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012185 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 +040012186 { # changed offset
12187 $ProblemType .= "_And_Layout";
12188 }
12189 }
12190 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12191 $ProblemType .= "_And_Type_Size";
12192 }
12193 }
12194 }
12195 else
12196 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012197 # TODO: Private_Field_Type rule?
12198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012199 if(not isPublic(\%Type1_Pure, $Member_Pos)
12200 or isUnnamed($Member_Name)) {
12201 next;
12202 }
12203 }
12204 if($ProblemType eq "Private_Field_Type_And_Size")
12205 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012206 }
12207 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12208 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012209 "Type_Name"=>$Type1_Pure{"Name"});
12210
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012211 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012212 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012213 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012214 }
12215 }
12216 if(not isPublic(\%Type1_Pure, $Member_Pos))
12217 { # do NOT check internal type changes
12218 next;
12219 }
12220 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012221 { # checking member type changes
12222 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12223
12224 my %DupProblems = ();
12225
12226 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012227 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012228 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012229 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012230 if(not defined $AllAffected)
12231 {
12232 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12233 next;
12234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012235 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012236
12237 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12238 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12239
12240 if(not defined $AllAffected)
12241 {
12242 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012243 }
12244 }
12245 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012246
12247 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 }
12249 }
12250 }
12251 }
12252 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12253 { # checking added members, public and private
12254 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12255 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012256 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012257 if($AddedField{$Member_Pos})
12258 { # added
12259 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12260 {
12261 my $ProblemType = "Added_Field";
12262 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012263 or isUnnamed($Member_Name))
12264 {
12265 if($Level eq "Source") {
12266 next;
12267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 $ProblemType = "Added_Private_Field";
12269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012270 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012271 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012272 {
12273 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12274 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012275 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 +040012276 { # changed offset
12277 $ProblemType .= "_And_Layout";
12278 }
12279 }
12280 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12281 $ProblemType .= "_And_Size";
12282 }
12283 }
12284 if($ProblemType eq "Added_Private_Field")
12285 { # skip added private fields
12286 next;
12287 }
12288 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12289 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012290 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291 }
12292 elsif($Type2_Pure{"Type"} eq "Union")
12293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012294 if($Level eq "Binary"
12295 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 {
12297 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12298 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012299 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012300 }
12301 else
12302 {
12303 %{$SubProblems{"Added_Union_Field"}{$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 }
12308 elsif($Type2_Pure{"Type"} eq "Enum")
12309 {
12310 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12311 next if($Member_Value eq "");
12312 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12313 "Target"=>$Member_Name,
12314 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012315 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012316 }
12317 }
12318 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012319
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012320 if($Type1_Pure{"Type"} eq "FuncPtr")
12321 {
12322 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12323 {
12324 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12325 next;
12326 }
12327
12328 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12329 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12330
12331 my $PName = "p".$PPos;
12332
12333 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12334 my %DupProblems = ();
12335
12336 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12337 {
12338 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12339 {
12340 if(not defined $AllAffected)
12341 {
12342 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12343 next;
12344 }
12345 }
12346
12347 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12348 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12349
12350 if(not defined $AllAffected)
12351 {
12352 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12353 }
12354 }
12355 }
12356
12357 %DupProblems = ();
12358 }
12359 }
12360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012361 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012362 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012363}
12364
12365sub isUnnamed($) {
12366 return $_[0]=~/\Aunnamed\d+\Z/;
12367}
12368
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012369sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012370{
12371 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012372 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12373 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12374 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12375 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012376 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012377 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012378 }
12379 return $TypeName;
12380}
12381
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012382sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012383{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012384 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012385 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12387 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12390 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012391 return () if(not $Type{"Type"});
12392 if($Type{"Type"} ne $Type_Type)
12393 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012394 return () if(not $Type{"BaseType"});
12395 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012396 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012397 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012398 return %Type;
12399}
12400
12401my %TypeSpecAttributes = (
12402 "Const" => 1,
12403 "Volatile" => 1,
12404 "ConstVolatile" => 1,
12405 "Restrict" => 1,
12406 "Typedef" => 1
12407);
12408
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012409sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012411 my ($TypeId, $Info) = @_;
12412 if(not $TypeId or not $Info
12413 or not $Info->{$TypeId}) {
12414 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012415 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012416 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12417 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12418 }
12419 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012420 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012421 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012422 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012424 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012425 return %Type;
12426}
12427
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012428sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012429{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012430 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012431 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012432 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12433 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012434 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012435 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12436 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012437 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12438 my $PLevel = 0;
12439 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12440 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012442 return $PLevel if(not $Type{"BaseType"});
12443 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12444 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12445 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446}
12447
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012448sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012450 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012452 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12453 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012454 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012455 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12456 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012457 return %Type if(not $Type{"BaseType"});
12458 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012459 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012460 return %Type;
12461}
12462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012463sub get_BaseTypeQual($$)
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 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12468 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012469 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012470 my $Qual = "";
12471 if($Type{"Type"} eq "Pointer") {
12472 $Qual .= "*";
12473 }
12474 elsif($Type{"Type"} eq "Ref") {
12475 $Qual .= "&";
12476 }
12477 elsif($Type{"Type"} eq "ConstVolatile") {
12478 $Qual .= "const volatile";
12479 }
12480 elsif($Type{"Type"} eq "Const"
12481 or $Type{"Type"} eq "Volatile"
12482 or $Type{"Type"} eq "Restrict") {
12483 $Qual .= lc($Type{"Type"});
12484 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012485 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012486 return $BQual.$Qual;
12487}
12488
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012489sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012491 my ($TypeId, $Info) = @_;
12492 if(not $TypeId or not $Info
12493 or not $Info->{$TypeId}) {
12494 return ();
12495 }
12496 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012497 return %Type if(not $Type{"BaseType"});
12498 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012499 {
12500 if($Info->{$BTid}) {
12501 return %{$Info->{$BTid}};
12502 }
12503 else { # something is going wrong
12504 return ();
12505 }
12506 }
12507 else {
12508 return %Type;
12509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012510}
12511
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012512sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012514 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012515 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012516 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12517 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012518}
12519
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012520sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012521{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012522 my $Symbol = $_[0];
12523 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12524}
12525
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012526sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012527 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12528}
12529
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012530sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012531{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012532 my ($SInfo, $LibVersion) = @_;
12533
12534 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012535 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012536 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012537 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012538 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012539 return 1;
12540 }
12541 }
12542 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012543 if(my $ShortName = $SInfo->{"ShortName"})
12544 {
12545 if(index($ShortName,"<")!=-1
12546 and index($ShortName,">")!=-1) {
12547 return 1;
12548 }
12549 }
12550
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012551 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012552}
12553
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012554sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012556 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012557 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012558 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012559 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012560 { # class specialization
12561 return 1;
12562 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012563 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012564 { # method specialization
12565 return 1;
12566 }
12567 }
12568 return 0;
12569}
12570
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012571sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012572{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012573 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012574
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012575 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 { # non-public global data
12577 return 0;
12578 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012579
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012580 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012581 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012582 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012583 }
12584
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012585 if($Symbol=~/\A_Z/)
12586 {
12587 if($Symbol=~/[CD][3-4]E/) {
12588 return 0;
12589 }
12590 }
12591
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012592 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012593 { # support for old ABI dumps in --headers-only mode
12594 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12595 {
12596 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12597 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012598 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012599 if(not $PType or $PType eq "Unknown") {
12600 return 0;
12601 }
12602 }
12603 }
12604 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012605 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012607 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 if($SkipSymbols{$LibVersion}{$Symbol})
12610 { # user defined symbols to ignore
12611 return 0;
12612 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012613
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012614 if($SymbolsListPath and not $SymbolsList{$Symbol})
12615 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012616 if(not $TargetHeadersPath or not $Header
12617 or not is_target_header($Header, 1))
12618 { # -symbols-list | -headers-list
12619 return 0;
12620 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012621 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012622
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012623 if($AppPath and not $SymbolsList_App{$Symbol})
12624 { # user defined symbols (in application)
12625 return 0;
12626 }
12627
12628 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12629
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012630 if($ClassId)
12631 {
12632 if(not isTargetType($ClassId, $LibVersion)) {
12633 return 0;
12634 }
12635 }
12636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012637 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12638 if(not $NameSpace and $ClassId)
12639 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012640 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012641 }
12642 if($NameSpace)
12643 { # user defined namespaces to ignore
12644 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12645 return 0;
12646 }
12647 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12648 { # nested namespaces
12649 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12650 return 0;
12651 }
12652 }
12653 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012654 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012656 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012657 { # --skip-headers or <skip_headers> (not <skip_including>)
12658 if($Skip==1) {
12659 return 0;
12660 }
12661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012663 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012664 { # user defined types
12665 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12666
12667 if(not $TypesList{$CName})
12668 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012669 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12670 {
12671 $CName=~s/\A\Q$NS\E\:\://g;
12672 }
12673
12674 if(not $TypesList{$CName})
12675 {
12676 my $Found = 0;
12677
12678 while($CName=~s/\:\:.+?\Z//)
12679 {
12680 if($TypesList{$CName})
12681 {
12682 $Found = 1;
12683 last;
12684 }
12685 }
12686
12687 if(not $Found) {
12688 return 0;
12689 }
12690 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012691 }
12692 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012693
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012694 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12695 { # non-target symbols
12696 return 0;
12697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012698 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012699 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012700 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12701 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012702 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012703 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12704 { # inline virtual methods
12705 if($Type=~/InlineVirt/) {
12706 return 1;
12707 }
12708 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12709 if(not $Allocable)
12710 { # check bases
12711 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12712 {
12713 if(not isCopyingClass($DCId, $LibVersion))
12714 { # exists a derived class without default c-tor
12715 $Allocable=1;
12716 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012718 }
12719 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012720 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012721 return 0;
12722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012723 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012724 else
12725 { # inline non-virtual methods
12726 return 0;
12727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012729 }
12730 }
12731 return 1;
12732}
12733
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012734sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012735{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012736 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012737 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12738 {
12739 if(link_symbol($Symbol, 1, "+Deps"))
12740 { # linker can find a new symbol
12741 # in the old-version library
12742 # So, it's not a new symbol
12743 next;
12744 }
12745 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012746 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012747 next;
12748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012749 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012750 }
12751}
12752
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012753sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012754{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012755 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012756 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12757 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012758 if(link_symbol($Symbol, 2, "+Deps"))
12759 { # linker can find an old symbol
12760 # in the new-version library
12761 next;
12762 }
12763 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012764 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012765 next;
12766 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 }
12769}
12770
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012771sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012772{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012773 my $Level = $_[0];
12774 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012775 { # checking added symbols
12776 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012777 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012778 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012779 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012781 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012782 { # checking removed symbols
12783 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012784 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012785 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012786 { # skip v-tables for templates, that should not be imported by applications
12787 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012788 if(my $CName = $VTableClass{$Symbol})
12789 {
12790 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12791 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012792 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012793 next;
12794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012795 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012796
12797 if($SkipSymbols{1}{$Symbol})
12798 { # user defined symbols to ignore
12799 next;
12800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012801 }
12802 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012803 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012804 }
12805 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12806 { # symbols for pure virtual methods cannot be called by clients
12807 next;
12808 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012809 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012810 }
12811}
12812
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012813sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012814{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012815 my ($LibVersion, $V) = @_;
12816 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12817 return $Cache{"checkDump"}{$LibVersion}{$V};
12818 }
12819 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012820}
12821
12822sub detectAdded_H($)
12823{
12824 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12826 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012827 if($Level eq "Source")
12828 { # remove symbol version
12829 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12830 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012831
12832 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12833 { # skip artificial constructors
12834 next;
12835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012836 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012837 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12838 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839 next;
12840 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012841 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012842 next;
12843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012844 if(not defined $CompleteSignature{1}{$Symbol}
12845 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12846 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012847 if($UsedDump{2}{"SrcBin"})
12848 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012849 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012850 { # support for old and different (!) ABI dumps
12851 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12852 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012853 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012854 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012855 {
12856 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12857 {
12858 if($Lang eq "C")
12859 { # support for old ABI dumps: missed extern "C" functions
12860 next;
12861 }
12862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012863 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012864 else
12865 {
12866 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012867 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012868 next;
12869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012870 }
12871 }
12872 }
12873 }
12874 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012875 }
12876 }
12877}
12878
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012879sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012880{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012881 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012882 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12883 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012884 if($Level eq "Source")
12885 { # remove symbol version
12886 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12887 $Symbol=$SN;
12888 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012889 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12890 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012891 next;
12892 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012893 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 next;
12895 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012896 if(not defined $CompleteSignature{2}{$Symbol}
12897 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012898 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012899 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012900 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012901 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012902 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012903 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12904 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012905 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012906 if($CheckHeadersOnly)
12907 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012908 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12909 {
12910 if($Lang eq "C")
12911 { # support for old ABI dumps: missed extern "C" functions
12912 next;
12913 }
12914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012915 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012916 else
12917 {
12918 if(not link_symbol($Symbol, 1, "-Deps"))
12919 { # skip removed inline symbols
12920 next;
12921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012922 }
12923 }
12924 }
12925 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012926 if(not checkDump(1, "2.15"))
12927 {
12928 if($Symbol=~/_IT_E\Z/)
12929 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12930 next;
12931 }
12932 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012933 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12934 {
12935 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12936 {
12937 if(defined $Constants{2}{$Short})
12938 {
12939 my $Val = $Constants{2}{$Short}{"Value"};
12940 if(defined $Func_ShortName{2}{$Val})
12941 { # old name defined to new
12942 next;
12943 }
12944 }
12945 }
12946
12947 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012948 $RemovedInt{$Level}{$Symbol} = 1;
12949 if($Level eq "Source")
12950 { # search for a source-compatible equivalent
12951 setAlternative($Symbol, $Level);
12952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012953 }
12954 }
12955}
12956
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012957sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012958{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012959 my $Level = $_[0];
12960 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012961 { # checking added symbols
12962 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012963 next if($CompleteSignature{2}{$Symbol}{"Private"});
12964 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012965 if($Level eq "Binary")
12966 {
12967 if($CompleteSignature{2}{$Symbol}{"InLine"})
12968 {
12969 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12970 { # skip inline non-virtual functions
12971 next;
12972 }
12973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012974 }
12975 else
12976 { # Source
12977 if($SourceAlternative_B{$Symbol}) {
12978 next;
12979 }
12980 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012983 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012984 { # checking removed symbols
12985 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012986 next if($CompleteSignature{1}{$Symbol}{"Private"});
12987 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012988 if($Level eq "Binary")
12989 {
12990 if($CompleteSignature{1}{$Symbol}{"InLine"})
12991 {
12992 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12993 { # skip inline non-virtual functions
12994 next;
12995 }
12996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012997 }
12998 else
12999 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013000 if(my $Alt = $SourceAlternative{$Symbol})
13001 {
13002 if(defined $CompleteSignature{1}{$Alt}
13003 and $CompleteSignature{1}{$Symbol}{"Const"})
13004 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013005 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013006 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013007 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013008 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013009 }
13010 else
13011 { # do NOT show removed symbol
13012 next;
13013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013014 }
13015 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013016 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013017 }
13018}
13019
13020sub addParamNames($)
13021{
13022 my $LibraryVersion = $_[0];
13023 return if(not keys(%AddIntParams));
13024 my $SecondVersion = $LibraryVersion==1?2:1;
13025 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13026 {
13027 next if(not keys(%{$AddIntParams{$Interface}}));
13028 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013029 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013030 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13031 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013032 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013033 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13034 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13035 {
13036 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13037 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13038 }
13039 }
13040 else {
13041 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13042 }
13043 }
13044 }
13045 }
13046}
13047
13048sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013049{ # detect changed typedefs to show
13050 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013051 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13052 {
13053 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013054 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13055 if(not $BName1 or isAnon($BName1)) {
13056 next;
13057 }
13058 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13059 if(not $BName2 or isAnon($BName2)) {
13060 next;
13061 }
13062 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013063 $ChangedTypedef{$Typedef} = 1;
13064 }
13065 }
13066}
13067
13068sub get_symbol_suffix($$)
13069{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013070 my ($Symbol, $Full) = @_;
13071 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013072 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013073 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013074 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013075 if(not $Full) {
13076 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13077 }
13078 return $Suffix;
13079}
13080
13081sub get_symbol_prefix($$)
13082{
13083 my ($Symbol, $LibVersion) = @_;
13084 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13085 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13086 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013087 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013088 }
13089 return $ShortName;
13090}
13091
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013092sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013093{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094 my $Symbol = $_[0];
13095 my $PSymbol = $Symbol;
13096 if(not defined $CompleteSignature{2}{$PSymbol}
13097 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13098 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13099 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013100 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013101 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013102 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013103 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013104 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13105 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013106 {
13107 if(defined $CompleteSignature{2}{$PSymbol}
13108 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13109 {
13110 $SourceAlternative{$Symbol} = $PSymbol;
13111 $SourceAlternative_B{$PSymbol} = $Symbol;
13112 if(not defined $CompleteSignature{1}{$PSymbol}
13113 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13114 $SourceReplacement{$Symbol} = $PSymbol;
13115 }
13116 }
13117 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013118 }
13119 else
13120 {
13121 foreach my $Sp ("KV", "VK", "K", "V")
13122 {
13123 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13124 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13125 {
13126 if(defined $CompleteSignature{2}{$PSymbol}
13127 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13128 {
13129 $SourceAlternative{$Symbol} = $PSymbol;
13130 $SourceAlternative_B{$PSymbol} = $Symbol;
13131 if(not defined $CompleteSignature{1}{$PSymbol}
13132 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13133 $SourceReplacement{$Symbol} = $PSymbol;
13134 }
13135 }
13136 }
13137 $PSymbol = $Symbol;
13138 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013139 }
13140 }
13141 }
13142 return "";
13143}
13144
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013145sub getSymKind($$)
13146{
13147 my ($Symbol, $LibVersion) = @_;
13148 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13149 {
13150 return "Global_Data";
13151 }
13152 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13153 {
13154 return "Method";
13155 }
13156 return "Function";
13157}
13158
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013159sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013160{
13161 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013162 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013163
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013164 mergeBases($Level);
13165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013166 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013167 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013169 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013170 next;
13171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013172 if(defined $CompleteSignature{1}{$Symbol}
13173 and $CompleteSignature{1}{$Symbol}{"Header"})
13174 { # double-check added symbol
13175 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013176 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013177 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013178 next;
13179 }
13180 if($Symbol=~/\A(_Z|\?)/)
13181 { # C++
13182 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13183 }
13184 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13185 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013186 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13187 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013188 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013189 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013190 {
13191 if($TName_Tid{1}{$AffectedClass_Name})
13192 { # class should exist in previous version
13193 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13194 { # old v-table is NOT copied by old applications
13195 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13196 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013197 "Target"=>get_Signature($Symbol, 2),
13198 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013199 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013202 }
13203 }
13204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013205 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13206 { # check all removed exported symbols
13207 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013208 next;
13209 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013210 if(defined $CompleteSignature{2}{$Symbol}
13211 and $CompleteSignature{2}{$Symbol}{"Header"})
13212 { # double-check removed symbol
13213 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013214 }
13215 if($CompleteSignature{1}{$Symbol}{"Private"})
13216 { # skip private methods
13217 next;
13218 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013219 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013220 next;
13221 }
13222 $CheckedSymbols{$Level}{$Symbol} = 1;
13223 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13224 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013225 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13226 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013227 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013228 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13229 {
13230 if($TName_Tid{2}{$AffectedClass_Name})
13231 { # class should exist in newer version
13232 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13233 { # old v-table is NOT copied by old applications
13234 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13235 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013236 "Target"=>get_Signature($OverriddenMethod, 1),
13237 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013238 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013241 }
13242 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013243 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013244 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013245 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013246 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013247 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013248 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013250 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013251 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013252 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013253 {
13254 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13255 "Target"=>$tr_name{$Symbol},
13256 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013257 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013258 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013259 else
13260 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013261 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013262 "Target"=>$tr_name{$Symbol},
13263 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013264 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013265 }
13266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013267 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013268 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013270 {
13271 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13272 "Target"=>$tr_name{$Symbol},
13273 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013274 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013275 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013276 else
13277 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013278 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013279 "Target"=>$tr_name{$Symbol},
13280 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013281 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013282 }
13283 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013284 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13285 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13286 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13287 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13288 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013289 {
13290 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013291 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013292 $ProblemType = "Global_Data_Symbol_Changed_Type";
13293 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13295 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013296 "Old_Type"=>$RTName1,
13297 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013298 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013299 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013300 }
13301 }
13302 }
13303 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013304 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013305 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013306 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013308 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013309 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013310 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013311 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13312 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013313 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013314 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013316 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013317 }
13318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13320 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013321 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013322 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013323 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013324 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013325 }
13326 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013327 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013328 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013329 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013331 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013332 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013333 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013334 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013335 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013336 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013337 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013338 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013339 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013341 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013342 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013343 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013344 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013347 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013348 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013349 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013350 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013351 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013352 { # "volatile" to non-"volatile"
13353
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013354 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013355 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013356 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013357 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013358 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013360 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013361 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013362 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013363 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013364 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013365 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013369 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013371 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13372 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013374 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013375 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013376 }
13377 }
13378 }
13379 }
13380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013381 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13382 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013383 $CurrentSymbol = $Symbol;
13384
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13386 if($Level eq "Source")
13387 { # remove symbol version
13388 $Symbol=$SN;
13389 }
13390 else
13391 { # Binary
13392 if(not $SV)
13393 { # symbol without version
13394 if(my $VSym = $SymVer{1}{$Symbol})
13395 { # the symbol is linked with versioned symbol
13396 if($CompleteSignature{2}{$VSym}{"MnglName"})
13397 { # show report for symbol@ver only
13398 next;
13399 }
13400 elsif(not link_symbol($VSym, 2, "-Deps"))
13401 { # changed version: sym@v1 to sym@v2
13402 # do NOT show report for symbol
13403 next;
13404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013405 }
13406 }
13407 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013408 my $PSymbol = $Symbol;
13409 if($Level eq "Source"
13410 and my $S = $SourceReplacement{$Symbol})
13411 { # take a source-compatible replacement function
13412 $PSymbol = $S;
13413 }
13414 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013415 { # private symbols
13416 next;
13417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013418 if(not defined $CompleteSignature{1}{$Symbol}
13419 or not defined $CompleteSignature{2}{$PSymbol})
13420 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013421 next;
13422 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13424 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13425 { # no mangled name
13426 next;
13427 }
13428 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13429 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 { # without a header
13431 next;
13432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013433
13434 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13435 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13436 { # became pure
13437 next;
13438 }
13439 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13440 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13441 { # became non-pure
13442 next;
13443 }
13444
13445 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13446 { # exported, target, inline virtual and pure virtual
13447 next;
13448 }
13449 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13450 { # exported, target, inline virtual and pure virtual
13451 next;
13452 }
13453
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013454 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013455 {
13456 if($CompleteSignature{1}{$Symbol}{"Data"}
13457 and $CompleteSignature{2}{$PSymbol}{"Data"})
13458 {
13459 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13460 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13461 if(defined $Value1)
13462 {
13463 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13464 if(defined $Value2)
13465 {
13466 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13467 if($Value1 ne $Value2)
13468 {
13469 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13470 "Old_Value"=>$Value1,
13471 "New_Value"=>$Value2,
13472 "Target"=>get_Signature($Symbol, 1) );
13473 }
13474 }
13475 }
13476 }
13477 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013478
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013479 if($CompleteSignature{2}{$PSymbol}{"Private"})
13480 {
13481 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13482 "Target"=>get_Signature_M($PSymbol, 2) );
13483 }
13484 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13485 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13486 {
13487 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13488 "Target"=>get_Signature_M($PSymbol, 2) );
13489 }
13490 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13491 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13492 {
13493 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13494 "Target"=>get_Signature_M($PSymbol, 2) );
13495 }
13496
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013497 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013498 mergeVirtualTables($Symbol, $Level);
13499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013500 if($COMPILE_ERRORS)
13501 { # if some errors occurred at the compiling stage
13502 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013503 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013504 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013505 { # missed information about parameters in newer version
13506 next;
13507 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013508 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013509 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013510 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013511 next;
13512 }
13513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013514 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013516 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013517 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13518 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013519 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13520 "Target"=>get_Signature($Symbol, 1)
13521 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013523 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013524 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13525 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013526 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013527 "Target"=>get_Signature($Symbol, 1)
13528 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013529 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13531 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013532 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013533 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013534 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013535 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13536 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13537 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013538 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013539 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013540 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13541 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013543 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013544 my $ProblemType = "Virtual_Method_Position";
13545 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13546 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013548 if(isUsedClass($Class_Id, 1, $Level))
13549 {
13550 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013551 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013552 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013553 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13554 next;
13555 }
13556 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013557 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013558 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13559 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013560 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013561 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013562 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 }
13565 }
13566 }
13567 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013568 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13569 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013570 { # do NOT check type changes in pure virtuals
13571 next;
13572 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013573 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013574 if($Symbol=~/\A(_Z|\?)/
13575 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013578 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013579 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013580 }
13581 }
13582 else
13583 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013584 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013585 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013586 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013587 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13588 last if($PType2_Name eq "...");
13589 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13590 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013592 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013593 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013594 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13595 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13597 $ParamPos_Prev = "lost";
13598 }
13599 }
13600 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013601 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013602 }
13603 if($ParamPos_Prev eq "lost")
13604 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013605 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013606 {
13607 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013608 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013609 $ProblemType = "Added_Unnamed_Parameter";
13610 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013611 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013612 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013613 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013614 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013615 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 }
13617 else
13618 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013619 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013620 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013621 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013622 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13623 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013624 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013625 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013626 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013627 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013628 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013629 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013630 "Param_Type"=>$PType2_Name,
13631 "Old_Value"=>$PName_Old,
13632 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013633 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013634 }
13635 }
13636 else
13637 {
13638 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 $ProblemType = "Added_Middle_Unnamed_Parameter";
13641 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013642 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013643 "Target"=>$PName,
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,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013646 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013647 }
13648 }
13649 }
13650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013651 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013652 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013653 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013656 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013658 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013659 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013660 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13661 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013662 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013663 }
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 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013668 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013669 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13670 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013671 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13672 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013674 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013675 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013676 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13677 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13679 $ParamPos_New = "lost";
13680 }
13681 }
13682 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013683 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013684 }
13685 if($ParamPos_New eq "lost")
13686 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013687 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 {
13689 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013690 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013691 $ProblemType = "Removed_Unnamed_Parameter";
13692 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013693 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013694 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013695 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013696 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013697 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013698 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013699 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013700 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013701 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013702 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013703 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013704 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013705 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013707 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013708 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013709 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013710 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013711 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013712 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013713 "Old_Value"=>$PName,
13714 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013715 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013716 }
13717 }
13718 else
13719 {
13720 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013721 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013722 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13723 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013724 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{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 Ponomarenko1bdef342012-03-19 17:23:47 +040013728 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013729 }
13730 }
13731 }
13732 }
13733 }
13734 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013735 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13736 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013737 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013738
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013739 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013740 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013741 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13742 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013743 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013744
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013745 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013746 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013747 if($SubProblemType eq "Return_Type_And_Size") {
13748 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13749 }
13750 elsif($SubProblemType eq "Return_Type_Format") {
13751 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13752 }
13753 else {
13754 $ProblemTypes{"Global_Data_Type"} = 1;
13755 }
13756
13757 # quals
13758 if($SubProblemType eq "Return_Type"
13759 or $SubProblemType eq "Return_Type_And_Size"
13760 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013761 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013762 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13763 { # const to non-const
13764 if($RR==2) {
13765 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13766 }
13767 else {
13768 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13769 }
13770 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013772 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13773 { # non-const to const
13774 if($RA==2) {
13775 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13776 }
13777 else {
13778 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13779 }
13780 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013781 }
13782 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013783 }
13784 else
13785 {
13786 # quals
13787 if($SubProblemType eq "Return_Type"
13788 or $SubProblemType eq "Return_Type_And_Size"
13789 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013791 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013792 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013793 if(addedQual($Old_Value, $New_Value, "volatile"))
13794 {
13795 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13796 if($Level ne "Source"
13797 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13798 $ProblemTypes{"Return_Type"} = 1;
13799 }
13800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013801 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013802 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13803 {
13804 if($RA==2) {
13805 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13806 }
13807 else {
13808 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13809 }
13810 if($Level ne "Source"
13811 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13812 $ProblemTypes{"Return_Type"} = 1;
13813 }
13814 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013815 }
13816 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013817 if($Level eq "Binary"
13818 and not $CompleteSignature{1}{$Symbol}{"Data"})
13819 {
13820 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13821 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13822 { # if one of the architectures is unknown
13823 # then set other arhitecture to unknown too
13824 ($Arch1, $Arch2) = ("unknown", "unknown");
13825 }
13826 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013827 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013828 {
13829 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13830 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13831 }
13832 else
13833 {
13834 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13835 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13836 }
13837
13838 if($SubProblemType eq "Return_Type_Became_Void")
13839 {
13840 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13841 { # parameters stack has been affected
13842 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013843 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013844 }
13845 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013847 }
13848 }
13849 }
13850 elsif($SubProblemType eq "Return_Type_From_Void")
13851 {
13852 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13853 { # parameters stack has been affected
13854 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013855 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013856 }
13857 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013859 }
13860 }
13861 }
13862 elsif($SubProblemType eq "Return_Type"
13863 or $SubProblemType eq "Return_Type_And_Size"
13864 or $SubProblemType eq "Return_Type_Format")
13865 {
13866 if($Conv1{"Method"} ne $Conv2{"Method"})
13867 {
13868 if($Conv1{"Method"} eq "stack")
13869 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013870 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013871 }
13872 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013873 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013874 }
13875 }
13876 else
13877 {
13878 if($Conv1{"Method"} eq "reg")
13879 {
13880 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13881 {
13882 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013883 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013884 }
13885 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013886 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013887 }
13888 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013889 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013890 }
13891 }
13892 }
13893 }
13894 }
13895 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013896
13897 if(not keys(%ProblemTypes))
13898 { # default
13899 $ProblemTypes{$SubProblemType} = 1;
13900 }
13901
13902 foreach my $ProblemType (keys(%ProblemTypes))
13903 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013904 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013906 }
13907 if($ReturnType1_Id and $ReturnType2_Id)
13908 {
13909 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013910 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13911
13912 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013913
13914 if($CompleteSignature{1}{$Symbol}{"Data"})
13915 {
13916 if($Level eq "Binary")
13917 {
13918 if(get_PLevel($ReturnType1_Id, 1)==0)
13919 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013920 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013921 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013922
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013923 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13924 {
13925 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013926 {
13927 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13928 {
13929 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13930 last;
13931 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013932 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013933 }
13934 }
13935 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013936 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013937 {
13938 if(defined $GlobalDataObject{1}{$Symbol}
13939 and defined $GlobalDataObject{2}{$Symbol})
13940 {
13941 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13942 my $New_Size = $GlobalDataObject{2}{$Symbol};
13943 if($Old_Size!=$New_Size)
13944 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013945 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013946 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013947 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013948 }
13949 }
13950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013951 }
13952 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013953
13954 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013955 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013956 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013957 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013958 my $NewLocation = "retval";
13959 if($SubLocation and $SubLocation ne "retval") {
13960 $NewLocation = "retval->".$SubLocation;
13961 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013962 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13963 }
13964 }
13965
13966 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13967 {
13968 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13969 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013970 my $NewLocation = "retval";
13971 if($SubLocation and $SubLocation ne "retval") {
13972 $NewLocation = "retval->".$SubLocation;
13973 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013974 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013975 }
13976 }
13977 }
13978
13979 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013980 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13981 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13982 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013983 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013984 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013985 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13986 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013987 if($ThisPtr1_Id and $ThisPtr2_Id)
13988 {
13989 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013990 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13991 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013992 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013993 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013994 {
13995 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013996 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013997 }
13998 }
13999 }
14000 }
14001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014002 if($Level eq "Binary") {
14003 mergeVTables($Level);
14004 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014005 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14006 $CheckedSymbols{$Level}{$Symbol} = 1;
14007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014008}
14009
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014010sub rmQuals($$)
14011{
14012 my ($Value, $Qual) = @_;
14013 if(not $Qual) {
14014 return $Value;
14015 }
14016 if($Qual eq "all")
14017 { # all quals
14018 $Qual = "const|volatile|restrict";
14019 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014020 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014021 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014022 }
14023 return $Value;
14024}
14025
14026sub cmpBTypes($$$$)
14027{
14028 my ($T1, $T2, $V1, $V2) = @_;
14029 $T1 = uncover_typedefs($T1, $V1);
14030 $T2 = uncover_typedefs($T2, $V2);
14031 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14032}
14033
14034sub addedQual($$$)
14035{
14036 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014037 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014038}
14039
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014040sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014041{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014042 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014043 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014044}
14045
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014046sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014047{
14048 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14049 $Old_Value = uncover_typedefs($Old_Value, $V1);
14050 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014051
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014052 if($Old_Value eq $New_Value)
14053 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014054 return 0;
14055 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014056 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014057 { # without a qual
14058 return 0;
14059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014060 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014061 { # became non-qual
14062 return 1;
14063 }
14064 else
14065 {
14066 my @BQ1 = getQualModel($Old_Value, $Qual);
14067 my @BQ2 = getQualModel($New_Value, $Qual);
14068 foreach (0 .. $#BQ1)
14069 { # removed qual
14070 if($BQ1[$_]==1
14071 and $BQ2[$_]!=1)
14072 {
14073 return 2;
14074 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014075 }
14076 }
14077 return 0;
14078}
14079
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014080sub getQualModel($$)
14081{
14082 my ($Value, $Qual) = @_;
14083 if(not $Qual) {
14084 return $Value;
14085 }
14086
14087 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014088 while($Value=~/(\w+)/)
14089 {
14090 my $W = $1;
14091
14092 if($W eq $Qual) {
14093 $Value=~s/\b$W\b/\@/g;
14094 }
14095 else {
14096 $Value=~s/\b$W\b//g;
14097 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014098 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014099
14100 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014101 $Value=~s/[^\*\&\w]+//g;
14102
14103 # modeling
14104 # int*const*const == 011
14105 # int**const == 001
14106 my @Model = ();
14107 my @Elems = split(/[\*\&]/, $Value);
14108 if(not @Elems) {
14109 return (0);
14110 }
14111 foreach (@Elems)
14112 {
14113 if($_ eq $Qual) {
14114 push(@Model, 1);
14115 }
14116 else {
14117 push(@Model, 0);
14118 }
14119 }
14120
14121 return @Model;
14122}
14123
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014124my %StringTypes = map {$_=>1} (
14125 "char*",
14126 "char const*"
14127);
14128
14129my %CharTypes = map {$_=>1} (
14130 "char",
14131 "char const"
14132);
14133
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014134sub showVal($$$)
14135{
14136 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014137 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014138 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014139 if(substr($Value, 0, 2) eq "_Z")
14140 {
14141 if(my $Unmangled = $tr_name{$Value}) {
14142 return $Unmangled;
14143 }
14144 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014145 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014146 { # strings
14147 return "\"$Value\"";
14148 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014149 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014150 { # characters
14151 return "\'$Value\'";
14152 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014153 if($Value eq "")
14154 { # other
14155 return "\'\'";
14156 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014157 return $Value;
14158}
14159
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014160sub getRegs($$$)
14161{
14162 my ($LibVersion, $Symbol, $Pos) = @_;
14163
14164 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14165 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014166 my %Regs = ();
14167 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14168 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014169 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014170 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14171 }
14172 }
14173
14174 return join(", ", sort keys(%Regs));
14175 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014176 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14177 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14178 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14179 {
14180 return "unknown";
14181 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014182
14183 return undef;
14184}
14185
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014186sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014187{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014188 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014189 if(not $Symbol) {
14190 return;
14191 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014192 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14193 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14194 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14195 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014196 if(not $PType1_Id
14197 or not $PType2_Id) {
14198 return;
14199 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014200
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014201 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014202 { # do not merge "this"
14203 if($PName1 eq "this" or $PName2 eq "this") {
14204 return;
14205 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014206 }
14207
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014208 my %Type1 = get_Type($PType1_Id, 1);
14209 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014210
14211 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14212
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014213 my %BaseType1 = get_BaseType($PType1_Id, 1);
14214 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014215
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014216 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014217
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014218 if($Level eq "Binary")
14219 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014220 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014221 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14222 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14223 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14224 {
14225 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014226 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014227 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014228 }
14229 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14230 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14231 {
14232 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014233 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014234 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014236 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014237
14238 if(defined $UsedDump{1}{"DWARF"}
14239 and defined $UsedDump{2}{"DWARF"})
14240 {
14241 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14242 {
14243 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14244 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014245
14246 if($Old_Regs ne "unknown"
14247 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014248 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014249 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014250 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014251 if($Old_Regs ne $New_Regs)
14252 {
14253 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14254 "Target"=>$PName1,
14255 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14256 "Old_Value"=>$Old_Regs,
14257 "New_Value"=>$New_Regs );
14258 }
14259 }
14260 elsif($Old_Regs and not $New_Regs)
14261 {
14262 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014263 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014264 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014265 "Old_Value"=>$Old_Regs );
14266 }
14267 elsif(not $Old_Regs and $New_Regs)
14268 {
14269 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14270 "Target"=>$PName1,
14271 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014272 "New_Value"=>$New_Regs );
14273 }
14274 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014275
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014276 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14277 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14278 {
14279 if($Old_Offset ne $New_Offset)
14280 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014281 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14282 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14283
14284 $Old_Offset = $Old_Offset - $Start1;
14285 $New_Offset = $New_Offset - $Start2;
14286
14287 if($Old_Offset ne $New_Offset)
14288 {
14289 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14290 "Target"=>$PName1,
14291 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14292 "Old_Value"=>$Old_Offset,
14293 "New_Value"=>$New_Offset );
14294 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014295 }
14296 }
14297 }
14298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014299 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014300 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14301 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014303 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014304 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14305 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014306 if(not checkDump(1, "2.13")
14307 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014308 { # support for old ABI dumps
14309 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014310 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014311 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014312 and $Value_Old eq "false" and $Value_New eq "0")
14313 { # int class::method ( bool p = 0 );
14314 # old ABI dumps: "false"
14315 # new ABI dumps: "0"
14316 $Value_Old = "0";
14317 }
14318 }
14319 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014320 if(not checkDump(1, "2.18")
14321 and checkDump(2, "2.18"))
14322 { # support for old ABI dumps
14323 if(not defined $Value_Old
14324 and substr($Value_New, 0, 2) eq "_Z") {
14325 $Value_Old = $Value_New;
14326 }
14327 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014328 if(defined $Value_Old)
14329 {
14330 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14331 if(defined $Value_New)
14332 {
14333 $Value_New = showVal($Value_New, $PType2_Id, 2);
14334 if($Value_Old ne $Value_New)
14335 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014336 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014337 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014338 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014339 "Old_Value"=>$Value_Old,
14340 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014341 }
14342 }
14343 else
14344 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014345 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014346 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014347 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014348 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014349 }
14350 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014351 elsif(defined $Value_New)
14352 {
14353 $Value_New = showVal($Value_New, $PType2_Id, 2);
14354 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14355 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014356 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014357 "New_Value"=>$Value_New );
14358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014360
14361 if($ChkRnmd)
14362 {
14363 if($PName1 and $PName2 and $PName1 ne $PName2
14364 and $PType1_Id!=-1 and $PType2_Id!=-1
14365 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14366 { # except unnamed "..." value list (Id=-1)
14367 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14368 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014369 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014370 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14371 "Old_Value"=>$PName1,
14372 "New_Value"=>$PName2,
14373 "New_Signature"=>get_Signature($Symbol, 2) );
14374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014375 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014376
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014377 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014378 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014380 foreach my $SubProblemType (keys(%SubProblems))
14381 { # add new problems, remove false alarms
14382 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14383 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014384
14385 # quals
14386 if($SubProblemType eq "Parameter_Type"
14387 or $SubProblemType eq "Parameter_Type_And_Size"
14388 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014389 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014390 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014391 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014392 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014393 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014394 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014395 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14396 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14397 }
14398 }
14399 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14400 {
14401 if(removedQual($Old_Value, $New_Value, "volatile")) {
14402 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014403 }
14404 }
14405 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14406 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14407 { # int to "int const"
14408 delete($SubProblems{$SubProblemType});
14409 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014410 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14412 { # "int const" to int
14413 delete($SubProblems{$SubProblemType});
14414 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014415 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14416 { # "const" to non-"const"
14417 if($RR==2) {
14418 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14419 }
14420 else {
14421 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14422 }
14423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014424 }
14425 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014426
14427 if($Level eq "Source")
14428 {
14429 foreach my $SubProblemType (keys(%SubProblems))
14430 {
14431 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14432 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14433
14434 if($SubProblemType eq "Parameter_Type")
14435 {
14436 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14437 delete($SubProblems{$SubProblemType});
14438 }
14439 }
14440 }
14441 }
14442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014443 foreach my $SubProblemType (keys(%SubProblems))
14444 { # modify/register problems
14445 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14446 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014447 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14448 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014450 my $NewProblemType = $SubProblemType;
14451 if($Old_Value eq "..." and $New_Value ne "...")
14452 { # change from "..." to "int"
14453 if($ParamPos1==0)
14454 { # ISO C requires a named argument before "..."
14455 next;
14456 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014457 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014458 }
14459 elsif($New_Value eq "..." and $Old_Value ne "...")
14460 { # change from "int" to "..."
14461 if($ParamPos2==0)
14462 { # ISO C requires a named argument before "..."
14463 next;
14464 }
14465 $NewProblemType = "Parameter_Became_VaList";
14466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014467 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014468 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 {
14470 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014471 if($Arch1 eq "unknown"
14472 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014473 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014474 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 ($Arch1, $Arch2) = ("unknown", "unknown");
14476 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014477 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014478 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014479 { # real
14480 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14481 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14482 }
14483 else
14484 { # model
14485 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14486 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14487 }
14488 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014490 if($Conv1{"Method"} eq "stack")
14491 {
14492 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14493 $NewProblemType = "Parameter_Type_And_Stack";
14494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014495 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014496 elsif($Conv1{"Method"} eq "reg")
14497 {
14498 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14499 $NewProblemType = "Parameter_Type_And_Register";
14500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014501 }
14502 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014503 elsif($Conv1{"Method"} ne "unknown"
14504 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014505 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014506 if($Conv1{"Method"} eq "stack") {
14507 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014509 elsif($Conv1{"Method"} eq "register") {
14510 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014511 }
14512 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014513 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14514 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014515 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014516 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014517 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014518 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014519 "New_Signature"=>get_Signature($Symbol, 2) );
14520 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014523 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014525 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014526 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14527 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014528 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014529 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014530 {
14531 my $NewProblemType = $SubProblemType;
14532 if($SubProblemType eq "DataType_Size")
14533 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014534 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014535 { # stack has been affected
14536 $NewProblemType = "DataType_Size_And_Stack";
14537 }
14538 }
14539 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014540 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014541 }
14542 }
14543}
14544
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014545sub find_ParamPair_Pos_byName($$$)
14546{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014547 my ($Name, $Symbol, $LibVersion) = @_;
14548 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014549 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014550 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14551 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 {
14553 return $ParamPos;
14554 }
14555 }
14556 return "lost";
14557}
14558
14559sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14560{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014561 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014562 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014563 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014564 {
14565 next if($Order eq "backward" and $ParamPos>$MediumPos);
14566 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014567 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14568 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014569 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014570 push(@Positions, $ParamPos);
14571 }
14572 }
14573 return @Positions;
14574}
14575
14576sub getTypeIdByName($$)
14577{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014578 my ($TypeName, $LibVersion) = @_;
14579 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014580}
14581
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014582sub diffTypes($$$)
14583{
14584 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14585 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14586 }
14587 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14588 { # skip recursive declarations
14589 return 0;
14590 }
14591
14592 pushType($_[0], $_[1], \@RecurTypes_Diff);
14593 my $Diff = diffTypes_I(@_);
14594 pop(@RecurTypes_Diff);
14595
14596 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14597}
14598
14599sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014600{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014601 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014602
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014603 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14604 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014605
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14607 { # equal types
14608 return 0;
14609 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014610 if($Type1_Pure{"Name"} eq "void")
14611 { # from void* to something
14612 return 0;
14613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014614 if($Type1_Pure{"Name"}=~/\*/
14615 or $Type2_Pure{"Name"}=~/\*/)
14616 { # compared in detectTypeChange()
14617 return 0;
14618 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014620 my %FloatType = map {$_=>1} (
14621 "float",
14622 "double",
14623 "long double"
14624 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014625
14626 my $T1 = $Type1_Pure{"Type"};
14627 my $T2 = $Type2_Pure{"Type"};
14628
14629 if($T1 eq "Struct"
14630 and $T2 eq "Class")
14631 { # compare as data structures
14632 $T2 = "Struct";
14633 }
14634
14635 if($T1 eq "Class"
14636 and $T2 eq "Struct")
14637 { # compare as data structures
14638 $T1 = "Struct";
14639 }
14640
14641 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014642 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014643 if($T1 eq "Intrinsic"
14644 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645 { # "int" to "enum"
14646 return 0;
14647 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014648 elsif($T2 eq "Intrinsic"
14649 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014650 { # "enum" to "int"
14651 return 0;
14652 }
14653 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014654 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014655 # ...
14656 return 1;
14657 }
14658 }
14659 else
14660 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014661 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014662 {
14663 if($FloatType{$Type1_Pure{"Name"}}
14664 or $FloatType{$Type2_Pure{"Name"}})
14665 { # "float" to "double"
14666 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014667 if($Level eq "Source")
14668 { # Safe
14669 return 0;
14670 }
14671 else {
14672 return 1;
14673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014674 }
14675 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014676 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014677 {
14678 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14679 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014680 if(not @Membs1
14681 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014682 { # private
14683 return 0;
14684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014685 if($#Membs1!=$#Membs2)
14686 { # different number of elements
14687 return 1;
14688 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014689 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014690 {
14691 foreach my $Pos (@Membs1)
14692 { # compare elements by name and value
14693 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14694 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14695 { # different names
14696 return 1;
14697 }
14698 }
14699 }
14700 else
14701 {
14702 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014703 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014704 if($Level eq "Source")
14705 {
14706 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14707 { # different names
14708 return 1;
14709 }
14710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014711
14712 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14713 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14714
14715 if($MT1{"Name"} ne $MT2{"Name"}
14716 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14717 {
14718 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14719 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14720
14721 if($PL1 ne $PL2)
14722 { # different pointer level
14723 return 1;
14724 }
14725
14726 # compare base types
14727 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14728 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14729
14730 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14731 { # different types
14732 return 1;
14733 }
14734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014735 }
14736 }
14737 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014738 else
14739 {
14740 # TODO: arrays, etc.
14741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014742 }
14743 return 0;
14744}
14745
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014746sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014747{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014748 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014749 if(not $Type1_Id or not $Type2_Id) {
14750 return ();
14751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014752 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014753 my %Type1 = get_Type($Type1_Id, 1);
14754 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014755 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14756 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014757
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014758 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14759 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 +040014760
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014761 if(defined $UsedDump{1}{"DWARF"})
14762 {
14763 if($Type1_Pure{"Name"} eq "__unknown__"
14764 or $Type2_Pure{"Name"} eq "__unknown__"
14765 or $Type1_Base{"Name"} eq "__unknown__"
14766 or $Type2_Base{"Name"} eq "__unknown__")
14767 { # Error ABI dump
14768 return ();
14769 }
14770 }
14771
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014772 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14773 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014774 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14775 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14776 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14777 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14778 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14779 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14780 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014781 if($Type1{"Name"} eq $Type2{"Name"})
14782 {
14783 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14784 { # will be reported in mergeTypes() as typedef problem
14785 return ();
14786 }
14787 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14788 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14789 if(%Typedef_1 and %Typedef_2)
14790 {
14791 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14792 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14793 { # const Typedef
14794 return ();
14795 }
14796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014797 }
14798 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14799 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014800 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014801 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14802 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014803 {
14804 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14805 "Old_Value"=>$Type1_Base{"Name"},
14806 "New_Value"=>$Type2_Base{"Name"},
14807 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014808 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014809 }
14810 else
14811 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014812 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014813 { # format change
14814 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14815 "Old_Value"=>$Type1_Base{"Name"},
14816 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014817 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014818 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014819 }
14820 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14821 {
14822 %{$LocalProblems{$Prefix."_BaseType"}}=(
14823 "Old_Value"=>$Type1_Base{"Name"},
14824 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014825 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014826 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014827 }
14828 }
14829 }
14830 }
14831 elsif($Type1{"Name"} ne $Type2{"Name"})
14832 { # type change
14833 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14834 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014835 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014836 and $Type1_Pure{"Name"} eq "void")
14837 {
14838 %{$LocalProblems{"Return_Type_From_Void"}}=(
14839 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014840 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014842 elsif($Prefix eq "Return"
14843 and $Type2_Pure{"Name"} eq "void")
14844 {
14845 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14846 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014847 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014849 else
14850 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014851 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014852 and $Type1{"Size"} and $Type2{"Size"}
14853 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014854 {
14855 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14856 "Old_Value"=>$Type1{"Name"},
14857 "New_Value"=>$Type2{"Name"},
14858 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014859 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 }
14861 else
14862 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014863 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014864 { # format change
14865 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14866 "Old_Value"=>$Type1{"Name"},
14867 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014868 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014869 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014870 }
14871 elsif(tNameLock($Type1_Id, $Type2_Id))
14872 { # FIXME: correct this condition
14873 %{$LocalProblems{$Prefix."_Type"}}=(
14874 "Old_Value"=>$Type1{"Name"},
14875 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014876 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014877 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014878 }
14879 }
14880 }
14881 }
14882 }
14883 if($Type1_PLevel!=$Type2_PLevel)
14884 {
14885 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14886 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14887 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014888 if($Level eq "Source")
14889 {
14890 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014891 "Old_Value"=>$Type1_PLevel,
14892 "New_Value"=>$Type2_PLevel);
14893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014894 else
14895 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014896 if($Type2_PLevel>$Type1_PLevel)
14897 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014898 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14899 "Old_Value"=>$Type1_PLevel,
14900 "New_Value"=>$Type2_PLevel);
14901 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014902 else
14903 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014904 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14905 "Old_Value"=>$Type1_PLevel,
14906 "New_Value"=>$Type2_PLevel);
14907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014908 }
14909 }
14910 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014911 if($Type1_Pure{"Type"} eq "Array"
14912 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014913 { # base_type[N] -> base_type[N]
14914 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014915 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014916 foreach my $SubProblemType (keys(%SubProblems))
14917 {
14918 $SubProblemType=~s/_Type/_BaseType/g;
14919 next if(defined $LocalProblems{$SubProblemType});
14920 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14921 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14922 }
14923 }
14924 }
14925 return %LocalProblems;
14926}
14927
14928sub tNameLock($$)
14929{
14930 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014931 my $Changed = 0;
14932 if(differentDumps("G"))
14933 { # different GCC versions
14934 $Changed = 1;
14935 }
14936 elsif(differentDumps("V"))
14937 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014938 if(not checkDump(1, "2.20")
14939 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014940 { # latest names update
14941 # 2.6: added restrict qualifier
14942 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014943 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014944 $Changed = 1;
14945 }
14946 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014947
14948 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14949 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14950
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014951 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14952 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14953
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014954 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014955 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014956 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014957 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014958 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014959 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014960 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014961 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014962 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014963 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014964 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14965 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14966 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014967 { # equal base types
14968 return 0;
14969 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014970
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014971 if(not checkDump(1, "2.13")
14972 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014973 { # broken array names in ABI dumps < 2.13
14974 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014975 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014976 return 0;
14977 }
14978 }
14979
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014980 if(not checkDump(1, "2.6")
14981 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014982 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014983 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014984 and $TN2=~/\brestrict\b/) {
14985 return 0;
14986 }
14987 }
14988
14989 if(not checkDump(1, "2.20")
14990 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014991 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014992 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14993 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014994 return 0;
14995 }
14996 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014997 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014998 else
14999 {
15000 # typedef struct {...} type_t
15001 # typedef struct type_t {...} type_t
15002 if(index($TN1, " ".$TN2)!=-1)
15003 {
15004 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15005 return 0;
15006 }
15007 }
15008 if(index($TN2, " ".$TN1)!=-1)
15009 {
15010 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15011 return 0;
15012 }
15013 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015014
15015 if($TT1 eq "FuncPtr"
15016 and $TT2 eq "FuncPtr")
15017 {
15018 my $TN1_C = $TN1;
15019 my $TN2_C = $TN2;
15020
15021 $TN1_C=~s/\b(struct|union) //g;
15022 $TN2_C=~s/\b(struct|union) //g;
15023
15024 if($TN1_C eq $TN2_C) {
15025 return 0;
15026 }
15027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015028 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015029
15030 my ($N1, $N2) = ($TN1, $TN2);
15031 $N1=~s/\b(struct|union) //g;
15032 $N2=~s/\b(struct|union) //g;
15033
15034 if($N1 eq $N2)
15035 { # QList<struct QUrl> and QList<QUrl>
15036 return 0;
15037 }
15038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 return 1;
15040}
15041
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015042sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015043{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015044 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015045 if(defined $Cache{"differentDumps"}{$Check}) {
15046 return $Cache{"differentDumps"}{$Check};
15047 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015048 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015049 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015050 if($Check eq "G")
15051 {
15052 if(getGccVersion(1) ne getGccVersion(2))
15053 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015054 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015055 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015056 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015057 if($Check eq "V")
15058 {
15059 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15060 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15061 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015062 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015063 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015065 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015066 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015067}
15068
15069sub formatVersion($$)
15070{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015071 my ($V, $Digits) = @_;
15072 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015073 return join(".", splice(@Elems, 0, $Digits));
15074}
15075
15076sub htmlSpecChars($)
15077{
15078 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015079 if(not $Str) {
15080 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015082 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15083 $Str=~s/</&lt;/g;
15084 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15085 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015086 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15087 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015088 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015089 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015090 $Str=~s/\n/<br\/>/g;
15091 $Str=~s/\"/&quot;/g;
15092 $Str=~s/\'/&#39;/g;
15093 return $Str;
15094}
15095
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015096sub xmlSpecChars($)
15097{
15098 my $Str = $_[0];
15099 if(not $Str) {
15100 return $Str;
15101 }
15102
15103 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15104 $Str=~s/</&lt;/g;
15105 $Str=~s/>/&gt;/g;
15106
15107 $Str=~s/\"/&quot;/g;
15108 $Str=~s/\'/&#39;/g;
15109
15110 return $Str;
15111}
15112
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015113sub xmlSpecChars_R($)
15114{
15115 my $Str = $_[0];
15116 if(not $Str) {
15117 return $Str;
15118 }
15119
15120 $Str=~s/&amp;/&/g;
15121 $Str=~s/&lt;/</g;
15122 $Str=~s/&gt;/>/g;
15123
15124 $Str=~s/&quot;/"/g;
15125 $Str=~s/&#39;/'/g;
15126
15127 return $Str;
15128}
15129
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130sub black_name($)
15131{
15132 my $Name = $_[0];
15133 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15134}
15135
15136sub highLight_Signature($)
15137{
15138 my $Signature = $_[0];
15139 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15140}
15141
15142sub highLight_Signature_Italic_Color($)
15143{
15144 my $Signature = $_[0];
15145 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15146}
15147
15148sub separate_symbol($)
15149{
15150 my $Symbol = $_[0];
15151 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15152 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15153 ($Name, $Spec, $Ver) = ($1, $2, $3);
15154 }
15155 return ($Name, $Spec, $Ver);
15156}
15157
15158sub cut_f_attrs($)
15159{
15160 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15161 return $2;
15162 }
15163 return "";
15164}
15165
15166sub highLight_Signature_PPos_Italic($$$$$)
15167{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015168 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15169 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015170 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15171 my $Return = "";
15172 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15173 $Return = $2;
15174 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015175 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015176 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015177 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015178 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015179 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015180 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015181 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015182 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015183 }
15184 return $Signature;
15185 }
15186 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15187 $Begin.=" " if($Begin!~/ \Z/);
15188 $End = cut_f_attrs($Signature);
15189 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015190 my ($Short, $Params) = split_Signature($Signature);
15191 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015192 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015193 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015194 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015195 $Part=~s/\A\s+|\s+\Z//g;
15196 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15197 if($Part=~/\([\*]+(\w+)\)/i) {
15198 $ParamName = $1;#func-ptr
15199 }
15200 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15201 $ParamName = $1;
15202 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015203 if(not $ParamName)
15204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 push(@Parts, $Part_Styled);
15206 next;
15207 }
15208 if($ItalicParams and not $TName_Tid{1}{$Part}
15209 and not $TName_Tid{2}{$Part})
15210 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015211 my $Style = "<i>$ParamName</i>";
15212
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015213 if($Param_Pos ne ""
15214 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015215 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015216 }
15217 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015218 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015219 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015220
15221 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015222 }
15223 $Part_Styled=~s/,(\w)/, $1/g;
15224 push(@Parts, $Part_Styled);
15225 }
15226 if(@Parts)
15227 {
15228 foreach my $Num (0 .. $#Parts)
15229 {
15230 if($Num==$#Parts)
15231 { # add ")" to the last parameter
15232 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15233 }
15234 elsif(length($Parts[$Num])<=45) {
15235 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15236 }
15237 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015238 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015239 }
15240 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015241 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015242 }
15243 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015244 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015245 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015246 $Signature=~s!\[\]![&#160;]!g;
15247 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015248 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15249 if($SymbolVersion) {
15250 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15251 }
15252 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253}
15254
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015255sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015256{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015257 my $Signature = $_[0];
15258 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15259 {
15260 $Signature=~s/\A\Q$ShortName\E\(//g;
15261 cut_f_attrs($Signature);
15262 $Signature=~s/\)\Z//;
15263 return ($ShortName, $Signature);
15264 }
15265
15266 # error
15267 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268}
15269
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015270sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015272 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015273 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015274 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15275 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276 foreach my $Pos (0 .. length($Params) - 1)
15277 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015278 my $S = substr($Params, $Pos, 1);
15279 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015280 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015281 }
15282 if($S eq "," and
15283 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015284 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015285 if($Comma)
15286 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015287 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015289 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015290 }
15291 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015292 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 }
15294 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015295 if(not $Sp)
15296 { # remove spaces
15297 foreach (@Parts)
15298 {
15299 s/\A //g;
15300 s/ \Z//g;
15301 }
15302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015303 return @Parts;
15304}
15305
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015306sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015307{
15308 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015309 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015311 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15312 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015313 $Center+=length($1);
15314 }
15315 foreach my $Pos (0 .. length($Sign)-1)
15316 {
15317 my $S = substr($Sign, $Pos, 1);
15318 if($S eq $Target)
15319 {
15320 if($B{"("}==$B{")"}
15321 and $B{"<"}==$B{">"}) {
15322 return $Center;
15323 }
15324 }
15325 if(defined $B{$S}) {
15326 $B{$S}+=1;
15327 }
15328 $Center+=1;
15329 }
15330 return 0;
15331}
15332
15333sub appendFile($$)
15334{
15335 my ($Path, $Content) = @_;
15336 return if(not $Path);
15337 if(my $Dir = get_dirname($Path)) {
15338 mkpath($Dir);
15339 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015340 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015341 print FILE $Content;
15342 close(FILE);
15343}
15344
15345sub writeFile($$)
15346{
15347 my ($Path, $Content) = @_;
15348 return if(not $Path);
15349 if(my $Dir = get_dirname($Path)) {
15350 mkpath($Dir);
15351 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015352 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015353 print FILE $Content;
15354 close(FILE);
15355}
15356
15357sub readFile($)
15358{
15359 my $Path = $_[0];
15360 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015361 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015362 local $/ = undef;
15363 my $Content = <FILE>;
15364 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015365 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015366 $Content=~s/\r/\n/g;
15367 }
15368 return $Content;
15369}
15370
15371sub get_filename($)
15372{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015373 if(defined $Cache{"get_filename"}{$_[0]}) {
15374 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015375 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015376 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15377 return ($Cache{"get_filename"}{$_[0]}=$1);
15378 }
15379 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015380}
15381
15382sub get_dirname($)
15383{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015384 if(defined $Cache{"get_dirname"}{$_[0]}) {
15385 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015386 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015387 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15388 return ($Cache{"get_dirname"}{$_[0]}=$1);
15389 }
15390 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391}
15392
15393sub separate_path($) {
15394 return (get_dirname($_[0]), get_filename($_[0]));
15395}
15396
15397sub esc($)
15398{
15399 my $Str = $_[0];
15400 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15401 return $Str;
15402}
15403
15404sub readLineNum($$)
15405{
15406 my ($Path, $Num) = @_;
15407 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015408 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015409 foreach (1 ... $Num) {
15410 <FILE>;
15411 }
15412 my $Line = <FILE>;
15413 close(FILE);
15414 return $Line;
15415}
15416
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015417sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015418{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015419 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015420 return () if(not $Path or not -f $Path);
15421 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015422 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15423 {
15424 foreach my $AttrVal (split(/;/, $1))
15425 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015426 if($AttrVal=~/(.+):(.+)/)
15427 {
15428 my ($Name, $Value) = ($1, $2);
15429 $Attributes{$Name} = $Value;
15430 }
15431 }
15432 }
15433 return \%Attributes;
15434}
15435
15436sub is_abs($) {
15437 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15438}
15439
15440sub get_abs_path($)
15441{ # abs_path() should NOT be called for absolute inputs
15442 # because it can change them
15443 my $Path = $_[0];
15444 if(not is_abs($Path)) {
15445 $Path = abs_path($Path);
15446 }
15447 return $Path;
15448}
15449
15450sub get_OSgroup()
15451{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015452 my $N = $Config{"osname"};
15453 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015454 return "macos";
15455 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015456 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015457 return "bsd";
15458 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015459 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015460 return "beos";
15461 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015462 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015463 return "symbian";
15464 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015465 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015466 return "windows";
15467 }
15468 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015469 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015470 }
15471}
15472
15473sub getGccVersion($)
15474{
15475 my $LibVersion = $_[0];
15476 if($GCC_VERSION{$LibVersion})
15477 { # dump version
15478 return $GCC_VERSION{$LibVersion};
15479 }
15480 elsif($UsedDump{$LibVersion}{"V"})
15481 { # old-version dumps
15482 return "unknown";
15483 }
15484 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15485 if(not $GccVersion) {
15486 return "unknown";
15487 }
15488 return $GccVersion;
15489}
15490
15491sub showArch($)
15492{
15493 my $Arch = $_[0];
15494 if($Arch eq "arm"
15495 or $Arch eq "mips") {
15496 return uc($Arch);
15497 }
15498 return $Arch;
15499}
15500
15501sub getArch($)
15502{
15503 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015504
15505 if($TargetArch) {
15506 return $TargetArch;
15507 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015508 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015509 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015510 return $CPU_ARCH{$LibVersion};
15511 }
15512 elsif($UsedDump{$LibVersion}{"V"})
15513 { # old-version dumps
15514 return "unknown";
15515 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015516
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015517 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015518}
15519
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015520sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015521{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015522 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015523
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015524 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015525 if(getArch(1) ne getArch(2)
15526 or getArch(1) eq "unknown"
15527 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015528 { # don't show architecture in the header
15529 $ArchInfo="";
15530 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015531 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015532 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015533 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015534 }
15535 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015536 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015537 }
15538 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015539 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015540 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015541
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015542 my $V1 = $Descriptor{1}{"Version"};
15543 my $V2 = $Descriptor{2}{"Version"};
15544
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015545 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15546 {
15547 my $M1 = $UsedDump{1}{"M"};
15548 my $M2 = $UsedDump{2}{"M"};
15549
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015550 my $M1S = $M1;
15551 my $M2S = $M2;
15552
15553 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15554 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15555
15556 if($M1S eq $M2S
15557 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015558 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015559 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15560 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015561 }
15562 else
15563 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015564 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15565 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015566 }
15567 }
15568 else
15569 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015570 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015571 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015572 }
15573
15574 $Title .= $ArchInfo;
15575
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015577 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015578 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015579 $Title = "<h1>".$Title."</h1>\n";
15580 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015581}
15582
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015583sub get_CheckedHeaders($)
15584{
15585 my $LibVersion = $_[0];
15586
15587 my @Headers = ();
15588
15589 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15590 {
15591 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015592
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015593 if(not is_target_header($File, $LibVersion)) {
15594 next;
15595 }
15596
15597 if(skipHeader($File, $LibVersion)) {
15598 next;
15599 }
15600
15601 push(@Headers, $Path);
15602 }
15603
15604 return @Headers;
15605}
15606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015607sub get_SourceInfo()
15608{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015609 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015610
15611 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015612 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015613 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15614 $CheckedHeaders .= "<div class='h_list'>\n";
15615 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 +040015616 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015617 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15618 my $Name = get_filename($Identity);
15619 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15620 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015621 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015622 $CheckedHeaders .= "</div>\n";
15623 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015624 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015625
15626 if(my @Sources = keys(%{$Registered_Sources{1}}))
15627 {
15628 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15629 $CheckedSources .= "<div class='h_list'>\n";
15630 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15631 {
15632 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15633 my $Name = get_filename($Identity);
15634 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15635 $CheckedSources .= $Name.$Comment."<br/>\n";
15636 }
15637 $CheckedSources .= "</div>\n";
15638 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15639 }
15640
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015641 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015642 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015643 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015644 $CheckedLibs .= "<div class='lib_list'>\n";
15645 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15646 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015647 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015648 $CheckedLibs .= $Library."<br/>\n";
15649 }
15650 $CheckedLibs .= "</div>\n";
15651 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015652 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015653
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015654 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15655}
15656
15657sub get_ObjTitle()
15658{
15659 if(defined $UsedDump{1}{"DWARF"}) {
15660 return "Objects";
15661 }
15662 else {
15663 return ucfirst($SLIB_TYPE)." Libraries";
15664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015665}
15666
15667sub get_TypeProblems_Count($$$)
15668{
15669 my ($TypeChanges, $TargetPriority, $Level) = @_;
15670 my $Type_Problems_Count = 0;
15671 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15672 {
15673 my %Kinds_Target = ();
15674 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15675 {
15676 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15677 {
15678 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015679 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15680 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 if($Kinds_Target{$Kind}{$Target}) {
15682 next;
15683 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015684
15685 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15686 {
15687 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15688 { # select a problem with the highest priority
15689 next;
15690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015691 }
15692 $Kinds_Target{$Kind}{$Target} = 1;
15693 $Type_Problems_Count += 1;
15694 }
15695 }
15696 }
15697 return $Type_Problems_Count;
15698}
15699
15700sub get_Summary($)
15701{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015702 my $Level = $_[0];
15703 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015704 $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 +040015705 %{$RESULT{$Level}} = (
15706 "Problems"=>0,
15707 "Warnings"=>0,
15708 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015709 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015710 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015711 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015712 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015713 {
15714 if(not defined $CompatRules{$Level}{$Kind})
15715 { # unknown rule
15716 if(not $UnknownRules{$Level}{$Kind})
15717 { # only one warning
15718 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15719 $UnknownRules{$Level}{$Kind}=1;
15720 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722 }
15723 }
15724 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015725 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15726 {
15727 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15728 {
15729 if(not defined $CompatRules{$Level}{$Kind})
15730 { # unknown rule
15731 if(not $UnknownRules{$Level}{$Kind})
15732 { # only one warning
15733 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15734 $UnknownRules{$Level}{$Kind}=1;
15735 }
15736 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15737 }
15738 }
15739 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015740 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015741 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015742 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015743 {
15744 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15745 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015746 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015747 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015748 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015749 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015750 $Added += 1;
15751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015752 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015753 {
15754 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015755 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 }
15757 else
15758 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015759 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015760 $I_Other += 1;
15761 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015762 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015763 $I_Problems_High += 1;
15764 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015765 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015766 $I_Problems_Medium += 1;
15767 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015768 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 $I_Problems_Low += 1;
15770 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015771 if(($Severity ne "Low" or $StrictCompat)
15772 and $Severity ne "Safe") {
15773 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 }
15775 }
15776 }
15777 }
15778 }
15779 }
15780 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015781 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015783 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015784 {
15785 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15786 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015787 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015788 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015789 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15790 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015791 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015792 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15793
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015794 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015795 { # select a problem with the highest priority
15796 next;
15797 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015798
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015799 if(($Severity ne "Low" or $StrictCompat)
15800 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015801 {
15802 if(defined $TotalAffected{$Level}{$Interface})
15803 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015804 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15805 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015806 }
15807 }
15808 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015809 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015811 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015812
15813 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15814
15815 if($MaxSeverity)
15816 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015817 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15818 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015819 }
15820 }
15821 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015822 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015824 }
15825 }
15826 }
15827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015828
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015829 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15830 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15831 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15832 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015833
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015834 %TypeChanges = (); # free memory
15835
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015836 # changed and removed public symbols
15837 my $SCount = keys(%{$CheckedSymbols{$Level}});
15838 if($ExtendedCheck)
15839 { # don't count external_func_0 for constants
15840 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015841 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015842 if($SCount)
15843 {
15844 my %Weight = (
15845 "High" => 100,
15846 "Medium" => 50,
15847 "Low" => 25
15848 );
15849 foreach (keys(%{$TotalAffected{$Level}})) {
15850 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015851 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015852 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015853 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015854 else {
15855 $RESULT{$Level}{"Affected"} = 0;
15856 }
15857
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015858 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15859 if($RESULT{$Level}{"Affected"}>=100) {
15860 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015861 }
15862
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015863 $RESULT{$Level}{"Problems"} += $Removed;
15864 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015865 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015866 if($StrictCompat) {
15867 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15868 }
15869 else {
15870 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015873 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015874 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015875 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015876 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015877 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015878 if($Severity eq "Safe")
15879 {
15880 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015881 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015882 elsif($Severity eq "Low")
15883 {
15884 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015885 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015886 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015887 }
15888
15889 if($C_Problems_Low)
15890 {
15891 if($StrictCompat) {
15892 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15893 }
15894 else {
15895 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015896 }
15897 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015898 if($RESULT{$Level}{"Problems"}
15899 and $RESULT{$Level}{"Affected"}) {
15900 $RESULT{$Level}{"Verdict"} = "incompatible";
15901 }
15902 else {
15903 $RESULT{$Level}{"Verdict"} = "compatible";
15904 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015905
15906 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15907 if(not $TotalTypes)
15908 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015909 $TotalTypes = keys(%{$TName_Tid{1}});
15910 }
15911
15912 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15913 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15914
15915 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15916
15917 if($ReportFormat eq "xml")
15918 { # XML
15919 # test info
15920 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15921 $TestInfo .= " <version1>\n";
15922 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015923 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015924 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15925 $TestInfo .= " </version1>\n";
15926
15927 $TestInfo .= " <version2>\n";
15928 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015929 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015930 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15931 $TestInfo .= " </version2>\n";
15932 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15933
15934 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015935 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015936 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015937 $TestResults .= " <headers>\n";
15938 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15939 {
15940 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15941 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15942 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15943 }
15944 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015946
15947 if(my @Sources = keys(%{$Registered_Sources{1}}))
15948 {
15949 $TestResults .= " <sources>\n";
15950 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15951 {
15952 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15953 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15954 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15955 }
15956 $TestResults .= " </sources>\n";
15957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015958
15959 $TestResults .= " <libs>\n";
15960 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15961 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015962 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015963 $TestResults .= " <name>$Library</name>\n";
15964 }
15965 $TestResults .= " </libs>\n";
15966
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015967 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015968 $TestResults .= " <types>".$TotalTypes."</types>\n";
15969
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015970 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15971 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015972 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15973
15974 # problem summary
15975 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15976 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15977
15978 $Problem_Summary .= " <problems_with_types>\n";
15979 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15980 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15981 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15982 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15983 $Problem_Summary .= " </problems_with_types>\n";
15984
15985 $Problem_Summary .= " <problems_with_symbols>\n";
15986 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15987 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15988 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015989 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015990 $Problem_Summary .= " </problems_with_symbols>\n";
15991
15992 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015993 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015994 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015996 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15997
15998 return ($TestInfo.$TestResults.$Problem_Summary, "");
15999 }
16000 else
16001 { # HTML
16002 # test info
16003 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016004 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016005
16006 if($TargetComponent eq "library") {
16007 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16008 }
16009 else {
16010 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016012
16013 my (@VInf1, @VInf2, $AddTestInfo) = ();
16014 if($Arch1 ne "unknown"
16015 and $Arch2 ne "unknown")
16016 { # CPU arch
16017 if($Arch1 eq $Arch2)
16018 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016019 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016020 }
16021 else
16022 { # go to the version number
16023 push(@VInf1, showArch($Arch1));
16024 push(@VInf2, showArch($Arch2));
16025 }
16026 }
16027 if($GccV1 ne "unknown"
16028 and $GccV2 ne "unknown"
16029 and $OStarget ne "windows")
16030 { # GCC version
16031 if($GccV1 eq $GccV2)
16032 { # go to the separate section
16033 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16034 }
16035 else
16036 { # go to the version number
16037 push(@VInf1, "gcc ".$GccV1);
16038 push(@VInf2, "gcc ".$GccV2);
16039 }
16040 }
16041 # show long version names with GCC version and CPU architecture name (if different)
16042 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16043 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16044 $TestInfo .= $AddTestInfo;
16045 #if($COMMON_LANGUAGE{1}) {
16046 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16047 #}
16048 if($ExtendedCheck) {
16049 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16050 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016051 if($JoinReport)
16052 {
16053 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016054 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016055 }
16056 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016057 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016058 }
16059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016060 $TestInfo .= "</table>\n";
16061
16062 # test results
16063 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016064 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016065
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016066 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016067 {
16068 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16069 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16070 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016071
16072 if(my @Sources = keys(%{$Registered_Sources{1}}))
16073 {
16074 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16075 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016077
16078 if(not $ExtendedCheck)
16079 {
16080 my $Libs_Link = "0";
16081 $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 +040016082 $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 +040016083 }
16084
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016085 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016086
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016087 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016088 if($JoinReport) {
16089 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16090 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016091 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016092 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016093 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16094 }
16095 else {
16096 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16097 }
16098 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016099 $TestResults .= "</table>\n";
16100
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016101 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016102 # problem summary
16103 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016104 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016105 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16106
16107 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016108 if($Added>0)
16109 {
16110 if($JoinReport) {
16111 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16112 }
16113 else {
16114 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16115 }
16116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016117 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016118 $Problem_Summary .= "<tr><th>Added Symbols</th><td>-</td><td".getStyle("I", "A", $Added).">$Added_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016119
16120 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016121 if($Removed>0)
16122 {
16123 if($JoinReport) {
16124 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16125 }
16126 else {
16127 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16128 }
16129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016130 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016131 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16132 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016133
16134 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016135 $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 +040016136 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016137 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16138 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016139
16140 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016141 $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 +040016142 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016143 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "M", $T_Problems_Medium).">$TM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016144
16145 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016146 $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 +040016147 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016148 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "L", $T_Problems_Low).">$TL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016149
16150 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 $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 +040016152 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016153 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16154 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016155
16156 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016157 $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 +040016158 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016159 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("I", "M", $I_Problems_Medium).">$IM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160
16161 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016162 $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 +040016163 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016164 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("I", "L", $I_Problems_Low).">$IL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016165
16166 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016167 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16168 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016170 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016171 $Problem_Summary .= "<tr><th>Problems with<br/>Constants</th><td>Low</td><td".getStyle("C", "L", $C_Problems_Low).">$ChangedConstants_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016172
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016173 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016174 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016175 {
16176 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016177 $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "S", $T_Other).">$TS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016178 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016180
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016181 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016182 {
16183 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016184 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "S", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016185 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016187
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016188 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016189 {
16190 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16191 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016192 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016193 }
16194
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 $META_DATA .= "tool_version:$TOOL_VERSION";
16196 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016197 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016198 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16199 }
16200}
16201
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016202sub getStyle($$$)
16203{
16204 my ($Subj, $Act, $Num) = @_;
16205 my %Style = (
16206 "A"=>"new",
16207 "R"=>"failed",
16208 "S"=>"passed",
16209 "L"=>"warning",
16210 "M"=>"failed",
16211 "H"=>"failed"
16212 );
16213 if($Num>0) {
16214 return " class='".$Style{$Act}."'";
16215 }
16216 return "";
16217}
16218
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016219sub show_number($)
16220{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016223 my $Num = cut_off_number($_[0], 2, 0);
16224 if($Num eq "0")
16225 {
16226 foreach my $P (3 .. 7)
16227 {
16228 $Num = cut_off_number($_[0], $P, 1);
16229 if($Num ne "0") {
16230 last;
16231 }
16232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016233 }
16234 if($Num eq "0") {
16235 $Num = $_[0];
16236 }
16237 return $Num;
16238 }
16239 return $_[0];
16240}
16241
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016242sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016243{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016244 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016245 if($num!~/\./)
16246 {
16247 $num .= ".";
16248 foreach (1 .. $digs_to_cut-1) {
16249 $num .= "0";
16250 }
16251 }
16252 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16253 {
16254 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16255 $num .= "0";
16256 }
16257 }
16258 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16259 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16260 }
16261 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016262 if($z) {
16263 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 return $num;
16266}
16267
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016268sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016270 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016271 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016272
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016273 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016274 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16275 {
16276 my $Header = $Constants{1}{$Constant}{"Header"};
16277 if(not $Header)
16278 { # added
16279 $Header = $Constants{2}{$Constant}{"Header"}
16280 }
16281
16282 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16283 {
16284 if(not defined $CompatRules{$Level}{$Kind}) {
16285 next;
16286 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016287 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016288 next;
16289 }
16290 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016292 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016293
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016294 if($ReportFormat eq "xml")
16295 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016296 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016297 {
16298 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016299 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 {
16301 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016302 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16303 {
16304 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16305 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16306 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016307
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016308 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16309 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16310 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016311 if($Overcome) {
16312 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16313 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016314 $CHANGED_CONSTANTS .= " </problem>\n";
16315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016316 $CHANGED_CONSTANTS .= " </constant>\n";
16317 }
16318 $CHANGED_CONSTANTS .= " </header>\n";
16319 }
16320 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16321 }
16322 else
16323 { # HTML
16324 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016325 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016326 {
16327 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016328 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016330 my $Report = "";
16331
16332 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16333 {
16334 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16335 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016336 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016337 $Number += 1;
16338 }
16339 if($Report)
16340 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016341 $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 +030016342 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016343 $Report = insertIDs($Report);
16344 }
16345 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016346 }
16347 $CHANGED_CONSTANTS .= "<br/>\n";
16348 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016349 if($CHANGED_CONSTANTS)
16350 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016351 my $Title = "Problems with Constants, $TargetSeverity Severity";
16352 if($TargetSeverity eq "Safe")
16353 { # Safe Changes
16354 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016355 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016356 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a><h2>$Title ($Number)</h2><hr/>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016357 }
16358 }
16359 return $CHANGED_CONSTANTS;
16360}
16361
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016362sub getTitle($$$)
16363{
16364 my ($Header, $Library, $NameSpace) = @_;
16365 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016366
16367 # if($Library and $Library!~/\.\w+\Z/) {
16368 # $Library .= " (.$LIB_EXT)";
16369 # }
16370
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016371 if($Header and $Library)
16372 {
16373 $Title .= "<span class='h_name'>$Header</span>";
16374 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16375 }
16376 elsif($Library) {
16377 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16378 }
16379 elsif($Header) {
16380 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16381 }
16382 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016383 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016384 }
16385 return $Title;
16386}
16387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016388sub get_Report_Added($)
16389{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016390 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016391 my $ADDED_INTERFACES = "";
16392 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016395 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016397 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016398 {
16399 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16400 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016401 if($Level eq "Source" and $ReportFormat eq "html")
16402 { # do not show library name in HTML report
16403 $DyLib = "";
16404 }
16405 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016406 }
16407 }
16408 }
16409 if($ReportFormat eq "xml")
16410 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016411 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016412 {
16413 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 {
16416 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016417 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016418 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16419 }
16420 $ADDED_INTERFACES .= " </library>\n";
16421 }
16422 $ADDED_INTERFACES .= " </header>\n";
16423 }
16424 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16425 }
16426 else
16427 { # HTML
16428 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016429 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016430 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016431 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016432 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016433 my %NameSpaceSymbols = ();
16434 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016435 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016436 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016437 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016438 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016439 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16440 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 foreach my $Interface (@SortedInterfaces)
16442 {
16443 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 my $Signature = get_Signature($Interface, 2);
16445 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016446 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016448 if($Interface=~/\A(_Z|\?)/)
16449 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016450 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016451 $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 +040016452 }
16453 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 }
16456 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016457 else
16458 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016459 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016460 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016461 }
16462 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016463 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016464 }
16465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016467 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 }
16470 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016471 if($ADDED_INTERFACES)
16472 {
16473 my $Anchor = "<a name='Added'></a>";
16474 if($JoinReport) {
16475 $Anchor = "<a name='".$Level."_Added'></a>";
16476 }
16477 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 }
16479 }
16480 return $ADDED_INTERFACES;
16481}
16482
16483sub get_Report_Removed($)
16484{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016485 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016486 my $REMOVED_INTERFACES = "";
16487 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016488 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016489 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016490 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016491 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016492 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016493 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016494 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16495 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016496 if($Level eq "Source" and $ReportFormat eq "html")
16497 { # do not show library name in HTML report
16498 $DyLib = "";
16499 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016500 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016501 }
16502 }
16503 }
16504 if($ReportFormat eq "xml")
16505 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016506 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016507 {
16508 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016509 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016510 {
16511 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016512 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16513 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016514 }
16515 $REMOVED_INTERFACES .= " </library>\n";
16516 }
16517 $REMOVED_INTERFACES .= " </header>\n";
16518 }
16519 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16520 }
16521 else
16522 { # HTML
16523 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016524 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016526 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016527 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016528 my %NameSpaceSymbols = ();
16529 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016530 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016531 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016532 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016533 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016534 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16535 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016536 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016537 {
16538 $Removed_Number += 1;
16539 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016540 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016542 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016543 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016544 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016546 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016547 $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 +040016548 }
16549 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016550 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016551 }
16552 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016553 else
16554 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016555 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016557 }
16558 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016559 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
16561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016562 }
16563 }
16564 $REMOVED_INTERFACES .= "<br/>\n";
16565 }
16566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016567 if($REMOVED_INTERFACES)
16568 {
16569 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16570 if($JoinReport) {
16571 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16572 }
16573 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 }
16575 }
16576 return $REMOVED_INTERFACES;
16577}
16578
16579sub getXmlParams($$)
16580{
16581 my ($Content, $Problem) = @_;
16582 return "" if(not $Content or not $Problem);
16583 my %XMLparams = ();
16584 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16585 {
16586 my $Macro = "\@".lc($Attr);
16587 if($Content=~/\Q$Macro\E/) {
16588 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16589 }
16590 }
16591 my @PString = ();
16592 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016593 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016594 }
16595 if(@PString) {
16596 return " ".join(" ", @PString);
16597 }
16598 else {
16599 return "";
16600 }
16601}
16602
16603sub addMarkup($)
16604{
16605 my $Content = $_[0];
16606 # auto-markup
16607 $Content=~s/\n[ ]*//; # spaces
16608 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16609 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016610 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016611 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16612 if($Content=~/\ANOTE:/)
16613 { # notes
16614 $Content=~s!(NOTE):!<b>$1</b>:!g;
16615 }
16616 else {
16617 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16618 }
16619 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16620 my @Keywords = (
16621 "void",
16622 "const",
16623 "static",
16624 "restrict",
16625 "volatile",
16626 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016627 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 );
16629 my $MKeys = join("|", @Keywords);
16630 foreach (@Keywords) {
16631 $MKeys .= "|non-".$_;
16632 }
16633 $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 +040016634
16635 # Markdown
16636 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16637 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016638 return $Content;
16639}
16640
16641sub applyMacroses($$$$)
16642{
16643 my ($Level, $Kind, $Content, $Problem) = @_;
16644 return "" if(not $Content or not $Problem);
16645 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16646 $Content = addMarkup($Content);
16647 # macros
16648 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16649 {
16650 my $Macro = "\@".lc($Attr);
16651 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016652 if(not defined $Value
16653 or $Value eq "") {
16654 next;
16655 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016656
16657 if(index($Content, $Macro)==-1) {
16658 next;
16659 }
16660
16661 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16662 and $Kind!~/_Type_/
16663 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016665 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016666 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 $Value = black_name($Value);
16668 }
16669 elsif($Value=~/\s/) {
16670 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16671 }
16672 elsif($Value=~/\A\d+\Z/
16673 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16674 { # bits to bytes
16675 if($Value % $BYTE_SIZE)
16676 { # bits
16677 if($Value==1) {
16678 $Value = "<b>".$Value."</b> bit";
16679 }
16680 else {
16681 $Value = "<b>".$Value."</b> bits";
16682 }
16683 }
16684 else
16685 { # bytes
16686 $Value /= $BYTE_SIZE;
16687 if($Value==1) {
16688 $Value = "<b>".$Value."</b> byte";
16689 }
16690 else {
16691 $Value = "<b>".$Value."</b> bytes";
16692 }
16693 }
16694 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016695 else
16696 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016697 $Value = "<b>".htmlSpecChars($Value)."</b>";
16698 }
16699 $Content=~s/\Q$Macro\E/$Value/g;
16700 }
16701
16702 if($Content=~/(\A|[^\@\w])\@\w/)
16703 {
16704 if(not $IncompleteRules{$Level}{$Kind})
16705 { # only one warning
16706 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16707 $IncompleteRules{$Level}{$Kind} = 1;
16708 }
16709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 return $Content;
16711}
16712
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016713sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016714{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016715 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016716 my $INTERFACE_PROBLEMS = "";
16717 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016718
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016719 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016720 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016721 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16722 if($SV and defined $CompatProblems{$Level}{$SN}) {
16723 next;
16724 }
16725 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016726 {
16727 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016728 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016730 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16731 my $DyLib = $Symbol_Library{1}{$Symbol};
16732 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016733 { # Symbol with Version
16734 $DyLib = $Symbol_Library{1}{$VSym};
16735 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016736 if(not $DyLib)
16737 { # const global data
16738 $DyLib = "";
16739 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016740 if($Level eq "Source" and $ReportFormat eq "html")
16741 { # do not show library name in HTML report
16742 $DyLib = "";
16743 }
16744 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16745 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016746 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016747 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16748 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016749 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016750 }
16751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16753 {
16754 delete($SymbolChanges{$Symbol}{$Kind});
16755 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016756 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016757 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016758 }
16759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016760 if(not keys(%{$SymbolChanges{$Symbol}})) {
16761 delete($SymbolChanges{$Symbol});
16762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016763 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 if($ReportFormat eq "xml")
16766 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016767 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 {
16769 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016770 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016771 {
16772 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016773 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16774 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016775 {
16776 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016777 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016778 {
16779 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16780 {
16781 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016782 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016783
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16785 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16786 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16787 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16788 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016789 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16790 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016792 $INTERFACE_PROBLEMS .= " </problem>\n";
16793 }
16794 }
16795 $INTERFACE_PROBLEMS .= " </symbol>\n";
16796 }
16797 $INTERFACE_PROBLEMS .= " </library>\n";
16798 }
16799 $INTERFACE_PROBLEMS .= " </header>\n";
16800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016801 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016802 }
16803 else
16804 { # HTML
16805 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016806 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016808 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016809 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 my (%NameSpaceSymbols, %NewSignature) = ();
16811 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016812 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016813 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016814 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016815 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016816 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016817 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 +040016818 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016819 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016820 my $Signature = get_Signature($Symbol, 1);
16821 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016822 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016823 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016825 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016826 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016828 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016829 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016830 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016831 }
16832 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16833 {
16834 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016835 $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 +040016836 $ProblemNum += 1;
16837 $ProblemsNum += 1;
16838 }
16839 }
16840 }
16841 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016842 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016843 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016844 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016845 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016846 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016847 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016848
16849 if($NameSpace)
16850 {
16851 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16852 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016853 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016854
16855 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol." ($ProblemNum)".$ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016856 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016857
16858 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016859 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016860 if($NameSpace) {
16861 $NSign = cut_Namespace($NSign, $NameSpace);
16862 }
16863 $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 +040016864 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016865
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016866 if($Symbol=~/\A(_Z|\?)/) {
16867 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16868 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016869
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016870 $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 +040016871 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 }
16873 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016874 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 }
16876 }
16877 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016878
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016879 if($INTERFACE_PROBLEMS)
16880 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16882 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16883 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 { # Safe Changes
16885 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016886 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016887 $INTERFACE_PROBLEMS = "<a name=\'".get_Anchor("Symbol", $Level, $TargetSeverity)."\'></a><a name=\'".get_Anchor("Interface", $Level, $TargetSeverity)."\'></a>\n<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016888 }
16889 }
16890 return $INTERFACE_PROBLEMS;
16891}
16892
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016893sub cut_Namespace($$)
16894{
16895 my ($N, $Ns) = @_;
16896 $N=~s/\b\Q$Ns\E:://g;
16897 return $N;
16898}
16899
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900sub get_Report_TypeProblems($$)
16901{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016902 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016903 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016904 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016905
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016906 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016908 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016909 {
16910 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16911 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016912 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016913 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016914 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016915 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016916 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016917
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016918 if($Severity eq "Safe"
16919 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016920 next;
16921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016922
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016923 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16924 {
16925 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16926 { # select a problem with the highest priority
16927 next;
16928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016929 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016930
16931 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 }
16933 }
16934 }
16935 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016936
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 my %Kinds_Locations = ();
16938 foreach my $TypeName (keys(%TypeChanges))
16939 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016940 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016941 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16942 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016943 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016945 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016946 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 { # other priority
16948 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16949 next;
16950 }
16951 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16952 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016953 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 { # duplicate target
16955 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16956 next;
16957 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016958 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016959 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016960 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 }
16962 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16963 delete($TypeChanges{$TypeName}{$Kind});
16964 }
16965 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016966 if(not keys(%{$TypeChanges{$TypeName}})) {
16967 delete($TypeChanges{$TypeName});
16968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016970
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016971 my @Symbols = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$CompatProblems{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 if($ReportFormat eq "xml")
16973 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016974 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 {
16976 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016977 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016979 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016980 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16981 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016982 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016983 {
16984 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16985 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16986 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16987 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16988 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16989 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016990 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16991 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016993 $TYPE_PROBLEMS .= " </problem>\n";
16994 }
16995 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016996 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016997 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016998 $TYPE_PROBLEMS .= showVTables($TypeName);
16999 }
17000 $TYPE_PROBLEMS .= " </type>\n";
17001 }
17002 $TYPE_PROBLEMS .= " </header>\n";
17003 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017004 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017005 }
17006 else
17007 { # HTML
17008 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017009 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017010 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017011 my (%NameSpace_Type) = ();
17012 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017013 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017014 }
17015 foreach my $NameSpace (sort keys(%NameSpace_Type))
17016 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017017 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017018 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 +040017019 foreach my $TypeName (@SortedTypes)
17020 {
17021 my $ProblemNum = 1;
17022 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017024 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17025 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017026 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017027 {
17028 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17029 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17030 {
17031 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017032 $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 +040017033 $ProblemNum += 1;
17034 $ProblemsNum += 1;
17035 }
17036 }
17037 }
17038 $ProblemNum -= 1;
17039 if($TYPE_REPORT)
17040 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017041 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017043 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017044 $ShowVTables = showVTables($TypeName);
17045 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017046
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017047 my $ShowType = show_Type($TypeName, 1, 1);
17048
17049 if($NameSpace)
17050 {
17051 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17052 $ShowType = cut_Namespace($ShowType, $NameSpace);
17053 $Affected = cut_Namespace($Affected, $NameSpace);
17054 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17055 }
17056
17057 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017058 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17059 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17060 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17061 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017062 }
17063 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017064 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 }
17066 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017068 if($TYPE_PROBLEMS)
17069 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017070 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17071 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017072 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017073 { # Safe Changes
17074 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017076 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 }
17078 }
17079 return $TYPE_PROBLEMS;
17080}
17081
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017082sub show_Type($$$)
17083{
17084 my ($Name, $Html, $LibVersion) = @_;
17085 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17086 $TType = lc($TType);
17087 if($TType=~/struct|union|enum/) {
17088 $Name=~s/\A\Q$TType\E //g;
17089 }
17090 if($Html) {
17091 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17092 }
17093 else {
17094 $Name = $TType." ".$Name;
17095 }
17096 return $Name;
17097}
17098
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017099sub get_Anchor($$$)
17100{
17101 my ($Kind, $Level, $Severity) = @_;
17102 if($JoinReport)
17103 {
17104 if($Severity eq "Safe") {
17105 return "Other_".$Level."_Changes_In_".$Kind."s";
17106 }
17107 else {
17108 return $Kind."_".$Level."_Problems_".$Severity;
17109 }
17110 }
17111 else
17112 {
17113 if($Severity eq "Safe") {
17114 return "Other_Changes_In_".$Kind."s";
17115 }
17116 else {
17117 return $Kind."_Problems_".$Severity;
17118 }
17119 }
17120}
17121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122sub showVTables($)
17123{
17124 my $TypeName = $_[0];
17125 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017126 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017127 if(defined $Type1{"VTable"}
17128 and keys(%{$Type1{"VTable"}}))
17129 {
17130 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017131 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017132 if(defined $Type2{"VTable"}
17133 and keys(%{$Type2{"VTable"}}))
17134 {
17135 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17136 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017137 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017139 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17140 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017141 }
17142 my $VTABLES = "";
17143 if($ReportFormat eq "xml")
17144 { # XML
17145 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017146 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017147 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017148 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017149 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17150 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017151 $VTABLES .= " </entry>\n";
17152 }
17153 $VTABLES .= " </vtable>\n\n";
17154 }
17155 else
17156 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017157 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017158 $VTABLES .= "<tr><th>Offset</th>";
17159 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017160 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017161 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017162 {
17163 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017164
17165 my $E1 = $Entries{$Index}{"E1"};
17166 my $E2 = $Entries{$Index}{"E2"};
17167
17168 if($E1 ne $E2
17169 and $E1!~/ 0x/
17170 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017171 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017172 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017173 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017174 $Color1 = " class='failed'";
17175 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 }
17177 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017178 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 }
17180 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017181 $VTABLES .= "<tr><th>".$Index."</th>\n";
17182 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17183 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017184 }
17185 $VTABLES .= "</table><br/>\n";
17186 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017187 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017188 }
17189 return $VTABLES;
17190 }
17191 }
17192 return "";
17193}
17194
17195sub simpleVEntry($)
17196{
17197 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017198 if(not defined $VEntry
17199 or $VEntry eq "") {
17200 return "";
17201 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017202
17203 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17205 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17206 if($VEntry=~/\A_ZThn.+\Z/) {
17207 $VEntry = "non-virtual thunk";
17208 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017209 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017210 # support for old GCC versions
17211 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17212 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17213 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017214 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17215 return $VEntry;
17216}
17217
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017218sub adjustParamPos($$$)
17219{
17220 my ($Pos, $Symbol, $LibVersion) = @_;
17221 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17222 {
17223 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17224 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17225 {
17226 return $Pos-1;
17227 }
17228
17229 return $Pos;
17230 }
17231
17232 return undef;
17233}
17234
17235sub getParamPos($$$)
17236{
17237 my ($Name, $Symbol, $LibVersion) = @_;
17238
17239 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17240 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17241 {
17242 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17243 foreach (keys(%{$Info->{"Param"}}))
17244 {
17245 if($Info->{"Param"}{$_}{"name"} eq $Name)
17246 {
17247 return $_;
17248 }
17249 }
17250 }
17251
17252 return undef;
17253}
17254
17255sub getParamName($)
17256{
17257 my $Loc = $_[0];
17258 $Loc=~s/\->.*//g;
17259 return $Loc;
17260}
17261
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017262sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017263{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017264 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017265
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017266 my $LIMIT = 10;
17267 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017268 $LIMIT = $AffectLimit;
17269 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017270
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017271 my @Kinds = sort keys(%{$Kinds_Locations});
17272 my %KLocs = ();
17273 foreach my $Kind (@Kinds)
17274 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017275 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 +030017276 $KLocs{$Kind} = \@Locs;
17277 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017278
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017279 my %SymLocKind = ();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017280 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017281 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017282 if(index($Symbol, "_Z")==0
17283 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017284 { # duplicated problems for C2 constructors, D2 and D0 destructors
17285 next;
17286 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017287
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017288 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017289 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017290 if(not defined $CompatProblems{$Level}{$Symbol}
17291 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17292 next;
17293 }
17294
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017295 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017297 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017298 next;
17299 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017300
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017301 if(index($Symbol, "\@")!=-1
17302 or index($Symbol, "\$")!=-1)
17303 {
17304 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17305
17306 if($Level eq "Source")
17307 { # remove symbol version
17308 $Symbol = $SN;
17309 }
17310
17311 if($SV and defined $CompatProblems{$Level}{$SN}
17312 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17313 { # duplicated problems for versioned symbols
17314 next;
17315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017316 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017317
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017318 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017319 if($Type_Name ne $Target_TypeName) {
17320 next;
17321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017322
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017323 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017324 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017325 }
17326 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017327
17328 # if(keys(%SymLocKind)>=$LIMIT)
17329 # {
17330 # last;
17331 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017332 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017333
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017334 %KLocs = (); # clear
17335
17336 my %SymSel = ();
17337 my $Num = 0;
17338 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017339 {
17340 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17341 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017342 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017343 {
17344 $SymSel{$Symbol}{"Loc"} = $Loc;
17345 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017346 last LOOP;
17347 }
17348 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017349
17350 $Num += 1;
17351
17352 if($Num>=$LIMIT) {
17353 last;
17354 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017355 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017357 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 if($ReportFormat eq "xml")
17360 { # XML
17361 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017362
17363 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017364 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017365 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017366 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017367 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017370 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017371 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017372 $Target .= " param=\"$PName\"";
17373 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017374 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017375 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017376 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017377 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017378 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017379 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017381
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017382 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017383 $Target .= " field=\"$1\"";
17384 }
17385
17386 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017387 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017388 $Affected .= " </symbol>\n";
17389 }
17390 $Affected .= " </affected>\n";
17391 }
17392 else
17393 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017394 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017395 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017396 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17397 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017398 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017399 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17400
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017401 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017402 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017403 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017404
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017405 if(keys(%SymLocKind)>$LIMIT) {
17406 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017407 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017408
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017409 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017410 if($Affected)
17411 {
17412 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017413 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymLocKind).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017414 }
17415 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017416
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017417 return $Affected;
17418}
17419
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017420sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017421{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017422 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017423 if($L2=~/\A(retval|this)\b/
17424 and $L1!~/\A(retval|this)\b/)
17425 {
17426 if($L1!~/\-\>/) {
17427 return 1;
17428 }
17429 elsif($L2=~/\-\>/) {
17430 return 1;
17431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 }
17433 return 0;
17434}
17435
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017436sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017437{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017438 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017439
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017440 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017441
17442 my $Location_I = $Location;
17443 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17444
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017445 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017447 if($Kind eq "Overridden_Virtual_Method"
17448 or $Kind eq "Overridden_Virtual_Method_B") {
17449 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17450 }
17451 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17452 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017453 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17454
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017455 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17456 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017457 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17458 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017460 if($ClassName eq $Problem{"Type_Name"}) {
17461 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17462 }
17463 else {
17464 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17465 }
17466 }
17467 else
17468 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017469 my $TypeID = undef;
17470
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017471 if($Location=~/retval/)
17472 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017473 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474 push(@Sentence, "Field \'".$Location."\' in return value");
17475 }
17476 else {
17477 push(@Sentence, "Return value");
17478 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017479
17480 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017481 }
17482 elsif($Location=~/this/)
17483 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017484 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017485 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17486 }
17487 else {
17488 push(@Sentence, "\'this\' pointer");
17489 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017490
17491 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017492 }
17493 else
17494 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017495
17496 my $PName = getParamName($Location);
17497 my $PPos = getParamPos($PName, $Symbol, 1);
17498
17499 if(index($Location, "->")!=-1) {
17500 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017501 }
17502 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017503 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017505 if($PName) {
17506 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017507 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017508
17509 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17510 }
17511
17512 if($Location!~/this/)
17513 {
17514 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017515 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017516 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017517 push(@Sentence, "(pointer)");
17518 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017519 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017520 push(@Sentence, "(reference)");
17521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017522 }
17523 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017525 if($Location eq "this") {
17526 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17527 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017528 else
17529 {
17530 my $Location_T = $Location;
17531 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17532
17533 my $TypeID_Problem = $TypeID;
17534 if($Location_T) {
17535 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17536 }
17537
17538 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17539 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17540 }
17541 else {
17542 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017544 }
17545 }
17546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017547 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017548 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 +040017549 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017550
17551 my $Sent = join(" ", @Sentence);
17552
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017553 $Sent=~s/->/./g;
17554
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017555 if($ReportFormat eq "xml")
17556 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017557 $Sent=~s/'//g;
17558 }
17559
17560 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017561}
17562
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017563sub getFieldType($$$)
17564{
17565 my ($Location, $TypeId, $LibVersion) = @_;
17566
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017567 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017568
17569 foreach my $Name (@Fields)
17570 {
17571 my %Info = get_BaseType($TypeId, $LibVersion);
17572
17573 foreach my $Pos (keys(%{$Info{"Memb"}}))
17574 {
17575 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17576 {
17577 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17578 last;
17579 }
17580 }
17581 }
17582
17583 return $TypeId;
17584}
17585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017586sub get_XmlSign($$)
17587{
17588 my ($Symbol, $LibVersion) = @_;
17589 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17590 my $Report = "";
17591 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17592 {
17593 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017594 my $Type = $Info->{"Param"}{$Pos}{"type"};
17595 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017596 foreach my $Typedef (keys(%ChangedTypedef))
17597 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017598 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17599 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017601 }
17602 $Report .= " <param pos=\"$Pos\">\n";
17603 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017604 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017605 $Report .= " </param>\n";
17606 }
17607 if(my $Return = $Info->{"Return"})
17608 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017609 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017610 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017611 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017612 $Report .= " </retval>\n";
17613 }
17614 return $Report;
17615}
17616
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017617sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017618{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017619 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017620 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017621 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017622 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017623 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17624 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017625 next;
17626 }
17627 $Report .= " <symbol name=\"$Symbol\">\n";
17628 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017629 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017630 {
17631 if(defined $CompleteSignature{1}{$Symbol}
17632 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17633 {
17634 $P1 = get_XmlSign($Symbol, 1);
17635 $S1 = get_Signature($Symbol, 1);
17636 }
17637 elsif($Symbol=~/\A(_Z|\?)/) {
17638 $S1 = $tr_name{$Symbol};
17639 }
17640 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017641 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017642 {
17643 if(defined $CompleteSignature{2}{$Symbol}
17644 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17645 {
17646 $P2 = get_XmlSign($Symbol, 2);
17647 $S2 = get_Signature($Symbol, 2);
17648 }
17649 elsif($Symbol=~/\A(_Z|\?)/) {
17650 $S2 = $tr_name{$Symbol};
17651 }
17652 }
17653 if($S1)
17654 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017655 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 $Report .= $P1;
17657 $Report .= " </old>\n";
17658 }
17659 if($S2 and $S2 ne $S1)
17660 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017661 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017662 $Report .= $P2;
17663 $Report .= " </new>\n";
17664 }
17665 $Report .= " </symbol>\n";
17666 }
17667 $Report .= "</symbols_info>\n";
17668 return $Report;
17669}
17670
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017671sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017672{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017673 my ($Level, $Report) = @_;
17674 if($ReportFormat eq "xml") {
17675 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017676 }
17677 if($StdOut)
17678 { # --stdout option
17679 print STDOUT $Report;
17680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017681 else
17682 {
17683 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017684 mkpath(get_dirname($RPath));
17685
17686 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17687 print REPORT $Report;
17688 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017689 }
17690}
17691
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017692sub getReport($)
17693{
17694 my $Level = $_[0];
17695 if($ReportFormat eq "xml")
17696 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017697 if($Level eq "Join")
17698 {
17699 my $Report = "<reports>\n";
17700 $Report .= getReport("Binary");
17701 $Report .= getReport("Source");
17702 $Report .= "</reports>\n";
17703 return $Report;
17704 }
17705 else
17706 {
17707 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17708 my ($Summary, $MetaData) = get_Summary($Level);
17709 $Report .= $Summary."\n";
17710 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17711 $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 +040017712
17713 # additional symbols info (if needed)
17714 # $Report .= get_Report_SymbolsInfo($Level);
17715
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017716 $Report .= "</report>\n";
17717 return $Report;
17718 }
17719 }
17720 else
17721 { # HTML
17722 my $CssStyles = readModule("Styles", "Report.css");
17723 my $JScripts = readModule("Scripts", "Sections.js");
17724 if($Level eq "Join")
17725 {
17726 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17727 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017728 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017729 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17730 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 +040017731 my ($BSummary, $BMetaData) = get_Summary("Binary");
17732 my ($SSummary, $SMetaData) = get_Summary("Source");
17733 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 +030017734 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017735 <br/>
17736 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017737 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17738 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017739 </div>";
17740 $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>";
17741 $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 +030017742 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017743 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017744 return $Report;
17745 }
17746 else
17747 {
17748 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017749 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17750 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17751 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 +040017752 if($Level eq "Binary")
17753 {
17754 if(getArch(1) eq getArch(2)
17755 and getArch(1) ne "unknown") {
17756 $Description .= " on ".showArch(getArch(1));
17757 }
17758 }
17759 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 +030017760 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017761 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17762 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17763 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017764 $Report .= "</div>\n<br/><br/><br/>\n";
17765 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017766 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017767 return $Report;
17768 }
17769 }
17770}
17771
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017772sub getLegend()
17773{
17774 return "<br/>
17775<table class='summary'>
17776<tr>
17777 <td class='new'>added</td>
17778 <td class='passed'>compatible</td>
17779</tr>
17780<tr>
17781 <td class='warning'>warning</td>
17782 <td class='failed'>incompatible</td>
17783</tr></table>\n";
17784}
17785
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017786sub createReport()
17787{
17788 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017789 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017790 writeReport("Join", getReport("Join"));
17791 }
17792 elsif($DoubleReport)
17793 { # default
17794 writeReport("Binary", getReport("Binary"));
17795 writeReport("Source", getReport("Source"));
17796 }
17797 elsif($BinaryOnly)
17798 { # --binary
17799 writeReport("Binary", getReport("Binary"));
17800 }
17801 elsif($SourceOnly)
17802 { # --source
17803 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017804 }
17805}
17806
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017807sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017808{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017809 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017810
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017811 $Footer .= "<hr/>\n";
17812 $Footer .= "<div class='footer' align='right'>";
17813 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17814 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017815 $Footer .= "<br/>\n";
17816
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017817 return $Footer;
17818}
17819
17820sub get_Report_Problems($$)
17821{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017822 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017823
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017824 my $Report = get_Report_TypeProblems($Severity, $Level);
17825 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017826 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017827 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017828
17829 if($Severity eq "Low" or $Severity eq "Safe") {
17830 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017831 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017832
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017833 if($ReportFormat eq "html")
17834 {
17835 if($Report)
17836 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017837 if($JoinReport)
17838 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017839 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017840 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17841 }
17842 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017843 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017846 else
17847 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017848 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017849 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17850 }
17851 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017852 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017854 }
17855 }
17856 }
17857 return $Report;
17858}
17859
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017860sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017861{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017862 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17863 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17864 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17865 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017866 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17867 <meta name=\"keywords\" content=\"$Keywords\" />
17868 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017869 <title>
17870 $Title
17871 </title>
17872 <style type=\"text/css\">
17873 $Styles
17874 </style>
17875 <script type=\"text/javascript\" language=\"JavaScript\">
17876 <!--
17877 $Scripts
17878 -->
17879 </script>
17880 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017881}
17882
17883sub insertIDs($)
17884{
17885 my $Text = $_[0];
17886 while($Text=~/CONTENT_ID/)
17887 {
17888 if(int($Content_Counter)%2) {
17889 $ContentID -= 1;
17890 }
17891 $Text=~s/CONTENT_ID/c_$ContentID/;
17892 $ContentID += 1;
17893 $Content_Counter += 1;
17894 }
17895 return $Text;
17896}
17897
17898sub checkPreprocessedUnit($)
17899{
17900 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017901 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017902 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017903 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017904
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017905 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017906 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017907 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017908 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017909 chomp($Line);
17910 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017911 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017912 $CurHeader = path_format($1, $OSgroup);
17913 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017914 $CurClass = "";
17915
17916 if(index($CurHeader, $TMP_DIR)==0) {
17917 next;
17918 }
17919
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017920 if(substr($CurHeaderName, 0, 1) eq "<")
17921 { # <built-in>, <command-line>, etc.
17922 $CurHeaderName = "";
17923 $CurHeader = "";
17924 }
17925
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017926 if($ExtraInfo)
17927 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017928 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017929 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17930 }
17931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017932 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017933 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017934 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017935 if($CurHeaderName)
17936 {
17937 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17938 and not $Registered_Headers{$Version}{$CurHeader})
17939 { # not a target
17940 next;
17941 }
17942 if(not is_target_header($CurHeaderName, 1)
17943 and not is_target_header($CurHeaderName, 2))
17944 { # user-defined header
17945 next;
17946 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017947 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017948 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017949
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017950 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017951 {
17952 my ($Name, $Value) = ($1, $2);
17953 if(not $Constants{$Version}{$Name}{"Access"})
17954 {
17955 $Constants{$Version}{$Name}{"Access"} = "public";
17956 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017957 if($CurHeaderName) {
17958 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17959 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017960 }
17961 }
17962 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17963 $Constants{$Version}{$1}{"Access"} = "private";
17964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017965 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017966 else
17967 {
17968 if(defined $ExtraDump)
17969 {
17970 if($Line=~/(\w+)\s*\(/)
17971 { # functions
17972 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17973 }
17974 #elsif($Line=~/(\w+)\s*;/)
17975 #{ # data
17976 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17977 #}
17978 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17979 $CurClass = $2;
17980 }
17981 }
17982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017983 }
17984 close(PREPROC);
17985 foreach my $Constant (keys(%{$Constants{$Version}}))
17986 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017987 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17988 {
17989 delete($Constants{$Version}{$Constant});
17990 next;
17991 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017992 if(not $ExtraDump and ($Constant=~/_h\Z/i
17993 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017994 { # skip
17995 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017996 }
17997 else {
17998 delete($Constants{$Version}{$Constant}{"Access"});
17999 }
18000 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018001 if($Debug)
18002 {
18003 mkpath($DEBUG_PATH{$Version});
18004 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018006}
18007
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018008sub uncoverConstant($$)
18009{
18010 my ($LibVersion, $Constant) = @_;
18011 return "" if(not $LibVersion or not $Constant);
18012 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18013 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18014 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18015 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018016
18017 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018018 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018019 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18020 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018021 {
18022 push(@RecurConstant, $Constant);
18023 my $Uncovered = uncoverConstant($LibVersion, $Value);
18024 if($Uncovered ne "") {
18025 $Value = $Uncovered;
18026 }
18027 pop(@RecurConstant);
18028 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018029
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018030 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018031 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018032 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18033 }
18034 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18035}
18036
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018037sub simpleConstant($$)
18038{
18039 my ($LibVersion, $Value) = @_;
18040 if($Value=~/\W/)
18041 {
18042 my $Value_Copy = $Value;
18043 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18044 {
18045 my $Word = $1;
18046 if($Value!~/$Word\s*\(/)
18047 {
18048 my $Val = uncoverConstant($LibVersion, $Word);
18049 if($Val ne "")
18050 {
18051 $Value=~s/\b$Word\b/$Val/g;
18052 }
18053 }
18054 }
18055 }
18056 return $Value;
18057}
18058
18059sub computeValue($)
18060{
18061 my $Value = $_[0];
18062
18063 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18064 return $1;
18065 }
18066
18067 if($Value=~/\A[\d\-\+()]+\Z/) {
18068 return eval($Value);
18069 }
18070
18071 return $Value;
18072}
18073
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018074my %IgnoreConstant = map {$_=>1} (
18075 "VERSION",
18076 "VERSIONCODE",
18077 "VERNUM",
18078 "VERS_INFO",
18079 "PATCHLEVEL",
18080 "INSTALLPREFIX",
18081 "VBUILD",
18082 "VPATCH",
18083 "VMINOR",
18084 "BUILD_STRING",
18085 "BUILD_TIME",
18086 "PACKAGE_STRING",
18087 "PRODUCTION",
18088 "CONFIGURE_COMMAND",
18089 "INSTALLDIR",
18090 "BINDIR",
18091 "CONFIG_FILE_PATH",
18092 "DATADIR",
18093 "EXTENSION_DIR",
18094 "INCLUDE_PATH",
18095 "LIBDIR",
18096 "LOCALSTATEDIR",
18097 "SBINDIR",
18098 "SYSCONFDIR",
18099 "RELEASE",
18100 "SOURCE_ID",
18101 "SUBMINOR",
18102 "MINOR",
18103 "MINNOR",
18104 "MINORVERSION",
18105 "MAJOR",
18106 "MAJORVERSION",
18107 "MICRO",
18108 "MICROVERSION",
18109 "BINARY_AGE",
18110 "INTERFACE_AGE",
18111 "CORE_ABI",
18112 "PATCH",
18113 "COPYRIGHT",
18114 "TIMESTAMP",
18115 "REVISION",
18116 "PACKAGE_TAG",
18117 "PACKAGEDATE",
18118 "NUMVERSION",
18119 "Release",
18120 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018121);
18122
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018123sub constantFilter($$$)
18124{
18125 my ($Name, $Value, $Level) = @_;
18126
18127 if($Level eq "Binary")
18128 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018129 if($Name=~/_t\Z/)
18130 { # __malloc_ptr_t
18131 return 1;
18132 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018133 foreach (keys(%IgnoreConstant))
18134 {
18135 if($Name=~/(\A|_)$_(_|\Z)/)
18136 { # version
18137 return 1;
18138 }
18139 if(/\A[A-Z].*[a-z]\Z/)
18140 {
18141 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18142 { # version
18143 return 1;
18144 }
18145 }
18146 }
18147 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18148 { # version
18149 return 1;
18150 }
18151 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18152 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18153 return 1;
18154 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018155
18156 if($Value=~/\A["'].*['"]/i)
18157 { # string
18158 return 0;
18159 }
18160
18161 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18162 { # static int gcry_pth_init
18163 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018164 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018165 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018166 return 1;
18167 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018168 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018169 { # foo(p)
18170 return 1;
18171 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018172 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018173 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018174 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018175 return 1;
18176 }
18177 }
18178
18179 return 0;
18180}
18181
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018182sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018183{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018184 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018185 foreach my $Constant (keys(%{$Constants{1}}))
18186 {
18187 if($SkipConstants{1}{$Constant})
18188 { # skipped by the user
18189 next;
18190 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018191
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018192 if(my $Header = $Constants{1}{$Constant}{"Header"})
18193 {
18194 if(not is_target_header($Header, 1)
18195 and not is_target_header($Header, 2))
18196 { # user-defined header
18197 next;
18198 }
18199 }
18200 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018201 next;
18202 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018203
18204 my $Old_Value = uncoverConstant(1, $Constant);
18205
18206 if(constantFilter($Constant, $Old_Value, $Level))
18207 { # separate binary and source problems
18208 next;
18209 }
18210
18211 if(not defined $Constants{2}{$Constant}{"Value"})
18212 { # removed
18213 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18214 "Target"=>$Constant,
18215 "Old_Value"=>$Old_Value );
18216 next;
18217 }
18218
18219 if($Constants{2}{$Constant}{"Value"} eq "")
18220 { # empty value
18221 # TODO: implement a rule
18222 next;
18223 }
18224
18225 my $New_Value = uncoverConstant(2, $Constant);
18226
18227 my $Old_Value_Pure = $Old_Value;
18228 my $New_Value_Pure = $New_Value;
18229
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018230 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18231 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18232 $New_Value_Pure=~s/(\W)\s+/$1/g;
18233 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018235 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018237 if($New_Value_Pure ne $Old_Value_Pure)
18238 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018239 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18240 { # complex values
18241 next;
18242 }
18243 if(computeValue($Old_Value) eq computeValue($New_Value))
18244 { # expressions
18245 next;
18246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018247 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18248 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18249 next;
18250 }
18251 if($Old_Value eq "0" and $New_Value eq "NULL")
18252 { # 0 => NULL
18253 next;
18254 }
18255 if($Old_Value eq "NULL" and $New_Value eq "0")
18256 { # NULL => 0
18257 next;
18258 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018259 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018260 "Target"=>$Constant,
18261 "Old_Value"=>$Old_Value,
18262 "New_Value"=>$New_Value );
18263 }
18264 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018265
18266 foreach my $Constant (keys(%{$Constants{2}}))
18267 {
18268 if(not defined $Constants{1}{$Constant}{"Value"})
18269 {
18270 if($SkipConstants{2}{$Constant})
18271 { # skipped by the user
18272 next;
18273 }
18274
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018275 if(my $Header = $Constants{2}{$Constant}{"Header"})
18276 {
18277 if(not is_target_header($Header, 1)
18278 and not is_target_header($Header, 2))
18279 { # user-defined header
18280 next;
18281 }
18282 }
18283 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018284 next;
18285 }
18286
18287 my $New_Value = uncoverConstant(2, $Constant);
18288 if(not defined $New_Value or $New_Value eq "") {
18289 next;
18290 }
18291
18292 if(constantFilter($Constant, $New_Value, $Level))
18293 { # separate binary and source problems
18294 next;
18295 }
18296
18297 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18298 "Target"=>$Constant,
18299 "New_Value"=>$New_Value );
18300 }
18301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018302}
18303
18304sub convert_integer($)
18305{
18306 my $Value = $_[0];
18307 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018308 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018309 return hex($Value);
18310 }
18311 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018312 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018313 return oct($Value);
18314 }
18315 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018316 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018317 return oct($Value);
18318 }
18319 else {
18320 return $Value;
18321 }
18322}
18323
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018324sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018325{
18326 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018327 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018328 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018329 {
18330 if($LibVersion==1)
18331 {
18332 printMsg("WARNING", "checking headers only");
18333 $CheckHeadersOnly = 1;
18334 }
18335 else {
18336 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18337 }
18338 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018339
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018340 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018341 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018342 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018343
18344 if($CheckUndefined)
18345 {
18346 my %UndefinedLibs = ();
18347
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018348 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18349
18350 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018351 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018352 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018353 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018354 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018355 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018356 if($Symbol_Library{$LibVersion}{$Symbol}
18357 or $DepSymbol_Library{$LibVersion}{$Symbol})
18358 { # exported by target library
18359 next;
18360 }
18361 if(index($Symbol, '@')!=-1)
18362 { # exported default symbol version (@@)
18363 $Symbol=~s/\@/\@\@/;
18364 if($Symbol_Library{$LibVersion}{$Symbol}
18365 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18366 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018367 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018368 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018369 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18370 $UndefinedLibs{$Path} = 1;
18371 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018372 }
18373 }
18374 }
18375 if($ExtraInfo)
18376 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018377 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018378 {
18379 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018380 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018381 foreach (@Paths)
18382 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018383 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018384 my ($Dir, $Name) = separate_path($_);
18385
18386 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018387 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018388 }
18389
18390 $Name = parse_libname($Name, "name", $OStarget);
18391 $Name=~s/\Alib//;
18392
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018393 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018394 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018395
18396 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18397 {
18398 $LibString = " -L".esc($Dir).$LibString;
18399 }
18400
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018401 writeFile($ExtraInfo."/libs-string", $LibString);
18402 }
18403 }
18404 }
18405
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018406 if($ExtraInfo) {
18407 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18408 }
18409
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018410 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018411 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018412 if($#LibPaths!=-1)
18413 {
18414 if(not keys(%{$Symbol_Library{$LibVersion}}))
18415 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018416 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018417 printMsg("WARNING", "checking headers only");
18418 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018419 }
18420 }
18421 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018422
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018423 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018424 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018425}
18426
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018427my %Prefix_Lib_Map=(
18428 # symbols for autodetecting library dependencies (by prefix)
18429 "pthread_" => ["libpthread"],
18430 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18431 "cairo_" => ["libcairo"],
18432 "gtk_" => ["libgtk-x11-2.0"],
18433 "atk_" => ["libatk-1.0"],
18434 "gdk_" => ["libgdk-x11-2.0"],
18435 "gl" => ["libGL"],
18436 "glu" => ["libGLU"],
18437 "popt" => ["libpopt"],
18438 "Py" => ["libpython"],
18439 "jpeg_" => ["libjpeg"],
18440 "BZ2_" => ["libbz2"],
18441 "Fc" => ["libfontconfig"],
18442 "Xft" => ["libXft"],
18443 "SSL_" => ["libssl"],
18444 "sem_" => ["libpthread"],
18445 "snd_" => ["libasound"],
18446 "art_" => ["libart_lgpl_2"],
18447 "dbus_g" => ["libdbus-glib-1"],
18448 "GOMP_" => ["libgomp"],
18449 "omp_" => ["libgomp"],
18450 "cms" => ["liblcms"]
18451);
18452
18453my %Pattern_Lib_Map=(
18454 "SL[a-z]" => ["libslang"]
18455);
18456
18457my %Symbol_Lib_Map=(
18458 # symbols for autodetecting library dependencies (by name)
18459 "pow" => "libm",
18460 "fmod" => "libm",
18461 "sin" => "libm",
18462 "floor" => "libm",
18463 "cos" => "libm",
18464 "dlopen" => "libdl",
18465 "deflate" => "libz",
18466 "inflate" => "libz",
18467 "move_panel" => "libpanel",
18468 "XOpenDisplay" => "libX11",
18469 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018470 "clock_gettime" => "librt",
18471 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018472);
18473
18474sub find_SymbolLibs($$)
18475{
18476 my ($LibVersion, $Symbol) = @_;
18477
18478 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18479 { # debug symbols
18480 return ();
18481 }
18482
18483 my %Paths = ();
18484
18485 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18486 {
18487 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18488 $Paths{$Path} = 1;
18489 }
18490 }
18491
18492 if(my $SymbolPrefix = getPrefix($Symbol))
18493 {
18494 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18495 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18496 }
18497
18498 if(not keys(%Paths))
18499 {
18500 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18501 {
18502 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18503 {
18504 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18505 $Paths{$Path} = 1;
18506 }
18507 }
18508 }
18509 }
18510
18511 if(not keys(%Paths))
18512 {
18513 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18514 {
18515 if($Symbol=~/\A$Prefix/)
18516 {
18517 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18518 {
18519 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18520 $Paths{$Path} = 1;
18521 }
18522 }
18523 }
18524 }
18525 }
18526
18527 if(not keys(%Paths))
18528 {
18529 if($SymbolPrefix)
18530 { # try to find a library by symbol prefix
18531 if($SymbolPrefix eq "inotify" and
18532 index($Symbol, "\@GLIBC")!=-1)
18533 {
18534 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18535 $Paths{$Path} = 1;
18536 }
18537 }
18538 else
18539 {
18540 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18541 $Paths{$Path} = 1;
18542 }
18543 }
18544 }
18545 }
18546
18547 if(my @Paths = keys(%Paths)) {
18548 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18549 }
18550 }
18551 return keys(%Paths);
18552}
18553
18554sub get_LibPath_Prefix($$)
18555{
18556 my ($LibVersion, $Prefix) = @_;
18557
18558 $Prefix = lc($Prefix);
18559 $Prefix=~s/[_]+\Z//g;
18560
18561 foreach ("-2", "2", "-1", "1", "")
18562 { # libgnome-2.so
18563 # libxml2.so
18564 # libdbus-1.so
18565 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18566 return $Path;
18567 }
18568 }
18569 return "";
18570}
18571
18572sub getPrefix($)
18573{
18574 my $Str = $_[0];
18575 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18576 { # XmuValidArea: Xmu
18577 return $1;
18578 }
18579 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18580 { # snfReadFont: snf
18581 return $1;
18582 }
18583 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18584 { # XRRTimes: XRR
18585 return $1;
18586 }
18587 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18588 { # H5HF_delete: H5
18589 return $1;
18590 }
18591 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18592 { # alarm_event_add: alarm_
18593 return $1;
18594 }
18595 elsif($Str=~/\A(([a-z])\2{1,})/i)
18596 { # ffopen
18597 return $1;
18598 }
18599 return "";
18600}
18601
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018602sub getSymbolSize($$)
18603{ # size from the shared library
18604 my ($Symbol, $LibVersion) = @_;
18605 return 0 if(not $Symbol);
18606 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18607 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18608 {
18609 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18610 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18611 {
18612 if($Size<0) {
18613 return -$Size;
18614 }
18615 }
18616 }
18617 return 0;
18618}
18619
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018620sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018621{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18622 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018623 my ($Name, $Type) = @_;
18624
18625 # single
18626 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018627 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018628 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018629 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018630 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018631
18632 # double
18633 if($Name=~/$DEFAULT_STD_PARMS/)
18634 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018635 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018636 {
18637 my ($ShortName, $FuncParams) = split_Signature($Name);
18638
18639 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18640 {
18641 if(index($FParam, "<")!=-1)
18642 {
18643 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18644 my $FParam_N = canonifyName($FParam, "T");
18645 if($FParam_N ne $FParam) {
18646 $Name=~s/\Q$FParam\E/$FParam_N/g;
18647 }
18648 }
18649 }
18650 }
18651 elsif($Type eq "T")
18652 {
18653 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18654
18655 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018656 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018657 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018658 my $FParam = $TParams[0];
18659 foreach my $Pos (1 .. $#TParams)
18660 {
18661 my $TParam = $TParams[$Pos];
18662 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18663 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18664 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018665 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018666 }
18667 }
18668 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018669 if($Type eq "S") {
18670 return formatName($Name, "S");
18671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018672 return $Name;
18673}
18674
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018675sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018676{
18677 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018678 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018679 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018680 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018681 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018682 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018683 next if($tr_name{$Symbol});
18684 $Symbol=~s/[\@\$]+(.*)\Z//;
18685 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018686 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018687 elsif(index($Symbol, "?")==0)
18688 {
18689 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018690 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018691 }
18692 else
18693 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018694 $tr_name{$Symbol} = $Symbol;
18695 $mangled_name_gcc{$Symbol} = $Symbol;
18696 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018697 }
18698 }
18699 if($#MnglNames1 > -1)
18700 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018701 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018702 foreach my $MnglName (@MnglNames1)
18703 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018704 if(my $Unmangled = pop(@UnmangledNames))
18705 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018706 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018707 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18708 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18709 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018710 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018711 and $tr_name{$MnglName}=~/vtable for (.+)/)
18712 { # bind class name and v-table symbol
18713 my $ClassName = $1;
18714 $ClassVTable{$ClassName} = $MnglName;
18715 $VTableClass{$MnglName} = $ClassName;
18716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018717 }
18718 }
18719 }
18720 if($#MnglNames2 > -1)
18721 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018722 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018723 foreach my $MnglName (@MnglNames2)
18724 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018725 if(my $Unmangled = pop(@UnmangledNames))
18726 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018727 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018728 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018730 }
18731 }
18732 return \%tr_name;
18733}
18734
18735sub link_symbol($$$)
18736{
18737 my ($Symbol, $RunWith, $Deps) = @_;
18738 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18739 return 1;
18740 }
18741 if($Deps eq "+Deps")
18742 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018743 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018744 return 1;
18745 }
18746 }
18747 return 0;
18748}
18749
18750sub link_symbol_internal($$$)
18751{
18752 my ($Symbol, $RunWith, $Where) = @_;
18753 return 0 if(not $Where or not $Symbol);
18754 if($Where->{$RunWith}{$Symbol})
18755 { # the exact match by symbol name
18756 return 1;
18757 }
18758 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18759 { # indirect symbol version, i.e.
18760 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018762 if($Where->{$RunWith}{$VSym}) {
18763 return 1;
18764 }
18765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018766 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018767 if($Sym and $Ver)
18768 { # search for the symbol with the same version
18769 # or without version
18770 if($Where->{$RunWith}{$Sym})
18771 { # old: foo@v|foo@@v
18772 # new: foo
18773 return 1;
18774 }
18775 if($Where->{$RunWith}{$Sym."\@".$Ver})
18776 { # old: foo|foo@@v
18777 # new: foo@v
18778 return 1;
18779 }
18780 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18781 { # old: foo|foo@v
18782 # new: foo@@v
18783 return 1;
18784 }
18785 }
18786 return 0;
18787}
18788
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018789sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018790{
18791 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018792 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018793 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018794 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018795 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018796 my $NM = get_CmdPath("nm");
18797 if(not $NM) {
18798 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018799 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018800 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018801 while(<APP>)
18802 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018803 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018804 push(@Imported, $1);
18805 }
18806 }
18807 close(APP);
18808 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018809 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018810 {
18811 my $DumpBinCmd = get_CmdPath("dumpbin");
18812 if(not $DumpBinCmd) {
18813 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18814 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018815 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018816 while(<APP>)
18817 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018818 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18819 push(@Imported, $1);
18820 }
18821 }
18822 close(APP);
18823 }
18824 else
18825 {
18826 my $ReadelfCmd = get_CmdPath("readelf");
18827 if(not $ReadelfCmd) {
18828 exitStatus("Not_Found", "can't find \"readelf\"");
18829 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018830 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018831 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018832 while(<APP>)
18833 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 if(defined $symtab)
18835 { # do nothing with symtab
18836 if(index($_, "'.dynsym'")!=-1)
18837 { # dynamic table
18838 $symtab = undef;
18839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018840 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018841 elsif(index($_, "'.symtab'")!=-1)
18842 { # symbol table
18843 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018844 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018845 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018846 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018847 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18848 if($Ndx eq "UND")
18849 { # only imported symbols
18850 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018851 }
18852 }
18853 }
18854 close(APP);
18855 }
18856 return @Imported;
18857}
18858
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018859my %ELF_BIND = map {$_=>1} (
18860 "WEAK",
18861 "GLOBAL"
18862);
18863
18864my %ELF_TYPE = map {$_=>1} (
18865 "FUNC",
18866 "IFUNC",
18867 "OBJECT",
18868 "COMMON"
18869);
18870
18871my %ELF_VIS = map {$_=>1} (
18872 "DEFAULT",
18873 "PROTECTED"
18874);
18875
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018877{ # read the line of 'readelf' output corresponding to the symbol
18878 my @Info = split(/\s+/, $_[0]);
18879 # Num: Value Size Type Bind Vis Ndx Name
18880 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018881 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018882 shift(@Info); # spaces
18883 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018884
18885 if($#Info==7)
18886 { # UND SYMBOL (N)
18887 if($Info[7]=~/\(\d+\)/) {
18888 pop(@Info);
18889 }
18890 }
18891
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018892 if($#Info!=6)
18893 { # other lines
18894 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018895 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018896 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018897 return () if(not defined $ELF_BIND{$Info[3]});
18898 return () if(not defined $ELF_VIS{$Info[4]});
18899 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18900 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18901 return ();
18902 }
18903 if($OStarget eq "symbian")
18904 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18905 if(index($Info[6], "_._.absent_export_")!=-1)
18906 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18907 return ();
18908 }
18909 $Info[6]=~s/\@.+//g; # remove version
18910 }
18911 if(index($Info[2], "0x") == 0)
18912 { # size == 0x3d158
18913 $Info[2] = hex($Info[2]);
18914 }
18915 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018916}
18917
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018918sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018919{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018920 my ($LibVersion, $Name) = @_;
18921 return "" if(not $LibVersion or not $Name);
18922 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18923 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018924 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018925 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18926}
18927
18928sub get_LibPath_I($$)
18929{
18930 my ($LibVersion, $Name) = @_;
18931 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018932 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018933 if(-f $Name)
18934 { # absolute path
18935 return $Name;
18936 }
18937 else
18938 { # broken
18939 return "";
18940 }
18941 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018942 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018943 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018944 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018945 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018946 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018947 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018948 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018949 }
18950 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18951 { # ldconfig default paths
18952 return $DefaultPath;
18953 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018954 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018955 { # search in default linker directories
18956 # and then in all system paths
18957 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018958 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018959 }
18960 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018961 if(not defined $Cache{"checkSystemFiles"}) {
18962 checkSystemFiles();
18963 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018964 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18965 return $AllObjects[0];
18966 }
18967 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18968 {
18969 if($ShortName ne $Name)
18970 { # FIXME: check this case
18971 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18972 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018973 }
18974 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018975 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018976 # can't find
18977 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018978}
18979
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018980sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018981{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018982 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18983 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018984
18985 my $Real_Path = realpath($Lib_Path);
18986
18987 if(not $Real_Path)
18988 { # broken link
18989 return ();
18990 }
18991
18992 my $Lib_Name = get_filename($Real_Path);
18993
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018994 if($ExtraInfo)
18995 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018996 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018997 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018998 }
18999
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019000 if($IsNeededLib)
19001 {
19002 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19003 return ();
19004 }
19005 }
19006 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019008
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019009 push(@RecurLib, $Lib_Name);
19010 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019011 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19012
19013 if(not $IsNeededLib)
19014 { # special cases: libstdc++ and libc
19015 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19016 {
19017 if($ShortName eq "libstdc++")
19018 { # libstdc++.so.6
19019 $STDCXX_TESTING = 1;
19020 }
19021 elsif($ShortName eq "libc")
19022 { # libc-2.11.3.so
19023 $GLIBC_TESTING = 1;
19024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019025 }
19026 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019027 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019028 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019029 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019030 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019031 mkpath(get_dirname($DebugPath));
19032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019033 if($OStarget eq "macos")
19034 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019035 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019036 if(not $NM) {
19037 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019038 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019039 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019040 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019041 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019042 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019043 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019044 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019045 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019046 else
19047 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019048 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019050 while(<LIB>)
19051 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019052 if($CheckUndefined)
19053 {
19054 if(not $IsNeededLib)
19055 {
19056 if(/ U _([\w\$]+)\s*\Z/)
19057 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019058 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019059 next;
19060 }
19061 }
19062 }
19063
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019064 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019065 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019066 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019067 if($IsNeededLib)
19068 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019069 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019070 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019071 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19072 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019075 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019076 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019077 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19078 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019079 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19080 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019081 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019082 setLanguage($LibVersion, "C++");
19083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019085 }
19086 }
19087 }
19088 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019089
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019090 if($Deps)
19091 {
19092 if($LIB_TYPE eq "dynamic")
19093 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019094
19095 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019096 if(not $OtoolCmd) {
19097 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019098 }
19099
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019100 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19101 while(<LIB>)
19102 {
19103 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19104 and $1 ne $Lib_Path) {
19105 $NeededLib{$1} = 1;
19106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019107 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019108 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019110 }
19111 }
19112 elsif($OStarget eq "windows")
19113 { # Windows *.dll, *.lib
19114 my $DumpBinCmd = get_CmdPath("dumpbin");
19115 if(not $DumpBinCmd) {
19116 exitStatus("Not_Found", "can't find \"dumpbin\"");
19117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019118 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019119 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019120 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019121 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019122 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019123 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019124 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019125 else
19126 { # write to pipe
19127 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019129 while(<LIB>)
19130 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19131 # 1198 4AD SetThreadToken (forwarded to ...)
19132 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019133 # 1 0 00005B30 ??0?N = ... (with pdb)
19134 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019135 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019136 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137 { # dynamic, static and forwarded symbols
19138 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019139 if($IsNeededLib)
19140 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019141 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019142 {
19143 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19144 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019147 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019148 {
19149 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19150 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019151 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19152 {
19153 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19154 setLanguage($LibVersion, "C++");
19155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019157 }
19158 }
19159 }
19160 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019161
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019162 if($Deps)
19163 {
19164 if($LIB_TYPE eq "dynamic")
19165 { # dependencies
19166 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19167 while(<LIB>)
19168 {
19169 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19170 and $1 ne $Lib_Path) {
19171 $NeededLib{path_format($1, $OSgroup)} = 1;
19172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019174 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019175 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019176 }
19177 }
19178 else
19179 { # Unix; *.so, *.a
19180 # Symbian: *.dso, *.lib
19181 my $ReadelfCmd = get_CmdPath("readelf");
19182 if(not $ReadelfCmd) {
19183 exitStatus("Not_Found", "can't find \"readelf\"");
19184 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019185 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019186 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019187 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019188 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019189 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019190 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019191 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019192 else
19193 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019194 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019195 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019196 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019197 while(<LIB>)
19198 {
19199 if($LIB_TYPE eq "dynamic")
19200 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019201 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019202 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019203 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019204 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019205 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019206 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019207 # do nothing with symtab
19208 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019210 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019211 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019212 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019213 next;
19214 }
19215 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019216 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019217 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019218 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019219 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019220 if($CheckUndefined)
19221 {
19222 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019223 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019224 }
19225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226 next;
19227 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019228 if($Bind eq "WEAK")
19229 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019230 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019231 if($Weak eq "-Weak")
19232 { # skip WEAK symbols
19233 next;
19234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019235 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019236 my $Short = $Symbol;
19237 $Short=~s/\@.+//g;
19238 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019239 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019240 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19241 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019243 if($IsNeededLib)
19244 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019245 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019246 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019247 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19248 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019251 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019252 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019253 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19254 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19255 if($Vers)
19256 {
19257 if($LIB_EXT eq "so")
19258 { # value
19259 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19260 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019262 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019263 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19264 {
19265 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19266 setLanguage($LibVersion, "C++");
19267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019269 }
19270 }
19271 }
19272 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019273
19274 if($Deps and $LIB_TYPE eq "dynamic")
19275 { # dynamic library specifics
19276 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19277 open(LIB, $Cmd." |");
19278
19279 while(<LIB>)
19280 {
19281 if(/NEEDED.+\[([^\[\]]+)\]/)
19282 { # dependencies:
19283 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19284 $NeededLib{$1} = 1;
19285 }
19286 }
19287
19288 close(LIB);
19289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019290 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019291 if($Vers)
19292 {
19293 if(not $IsNeededLib and $LIB_EXT eq "so")
19294 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019295 my %Found = ();
19296
19297 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019298 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019299 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019300 next if(index($Symbol,"\@")==-1);
19301 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019302 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019303 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019304 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019305 if($Symbol_SameValue ne $Symbol
19306 and index($Symbol_SameValue,"\@")==-1)
19307 {
19308 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019309 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019310 last;
19311 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019312 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019313 }
19314 }
19315
19316 # default
19317 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19318 {
19319 next if(defined $Found{$Symbol});
19320 next if(index($Symbol,"\@\@")==-1);
19321
19322 if($Symbol=~/\A([^\@]*)\@\@/
19323 and not $SymVer{$LibVersion}{$1})
19324 {
19325 $SymVer{$LibVersion}{$1} = $Symbol;
19326 $Found{$Symbol} = 1;
19327 }
19328 }
19329
19330 # non-default
19331 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19332 {
19333 next if(defined $Found{$Symbol});
19334 next if(index($Symbol,"\@")==-1);
19335
19336 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19337 and not $SymVer{$LibVersion}{$1})
19338 {
19339 $SymVer{$LibVersion}{$1} = $Symbol;
19340 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019341 }
19342 }
19343 }
19344 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019345 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019346 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019347 foreach my $DyLib (sort keys(%NeededLib))
19348 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019349 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19350
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019351 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19352 {
19353 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19354 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19355 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019357 }
19358 }
19359 pop(@RecurLib);
19360 return $Library_Symbol{$LibVersion};
19361}
19362
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019363sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019364{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019365 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019366 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019367 return keys(%Prefixes);
19368}
19369
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019370sub get_prefixes_I($$)
19371{
19372 foreach my $P (@{$_[0]})
19373 {
19374 my @Parts = reverse(split(/[\/\\]+/, $P));
19375 my $Name = $Parts[0];
19376 foreach (1 .. $#Parts)
19377 {
19378 $_[1]->{$Name}{$P} = 1;
19379 last if($_>4 or $Parts[$_] eq "include");
19380 $Name = $Parts[$_].$SLASH.$Name;
19381 }
19382 }
19383}
19384
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019385sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019386{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019387 $Cache{"checkSystemFiles"} = 1;
19388
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019389 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019390
19391 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019392 {
19393 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019394
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019395 my @Files = cmd_find($DevelPath,"f");
19396 foreach my $Link (cmd_find($DevelPath,"l"))
19397 { # add symbolic links
19398 if(-f $Link) {
19399 push(@Files, $Link);
19400 }
19401 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019402
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019403 # search for headers in /usr/lib
19404 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19405 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19406 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019407
19408 # search for libraries in /usr/lib (including symbolic links)
19409 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19410 foreach my $Path (@Libs)
19411 {
19412 my $N = get_filename($Path);
19413 $SystemObjects{$N}{$Path} = 1;
19414 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019415 }
19416 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019417
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019418 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019419 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019420 next if(not -d $DevelPath);
19421 # search for all header files in the /usr/include
19422 # with or without extension (ncurses.h, QtCore, ...)
19423 push(@SysHeaders, cmd_find($DevelPath,"f"));
19424 foreach my $Link (cmd_find($DevelPath,"l"))
19425 { # add symbolic links
19426 if(-f $Link) {
19427 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019429 }
19430 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019431 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432}
19433
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019434sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019435{
19436 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019437 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019438 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19439 {
19440 if(not -e $Dest) {
19441 exitStatus("Access_Error", "can't access \'$Dest\'");
19442 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019443 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19445 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019446 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019447 }
19448 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019449 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019450}
19451
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019452sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019453{
19454 my ($Path, $LibVersion) = @_;
19455 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019456 my $Name = get_filename($Path);
19457 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019458 return 1;
19459 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019460 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019461 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19462 return 1;
19463 }
19464 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19465 {
19466 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19467 return 1;
19468 }
19469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019470 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019471 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019472 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019473 return 1;
19474 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019475 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019476 return 1;
19477 }
19478 }
19479 return 0;
19480}
19481
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019482sub specificHeader($$)
19483{
19484 my ($Header, $Spec) = @_;
19485 my $Name = get_filename($Header);
19486
19487 if($Spec eq "windows")
19488 {# MS Windows
19489 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19490 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19491 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19492 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19493 my @Dirs = (
19494 "win32",
19495 "win64",
19496 "win",
19497 "windows",
19498 "msvcrt"
19499 ); # /gsf-win32/
19500 if(my $DIRs = join("|", @Dirs)) {
19501 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19502 }
19503 }
19504 elsif($Spec eq "macos")
19505 { # Mac OS
19506 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19507 }
19508
19509 return 0;
19510}
19511
19512sub skipAlienHeader($)
19513{
19514 my $Path = $_[0];
19515 my $Name = get_filename($Path);
19516 my $Dir = get_dirname($Path);
19517
19518 if($Tolerance=~/2/)
19519 { # 2 - skip internal headers
19520 my @Terms = (
19521 "p",
19522 "priv",
19523 "int",
19524 "impl",
19525 "implementation",
19526 "internal",
19527 "private",
19528 "old",
19529 "compat",
19530 "debug",
19531 "test",
19532 "gen"
19533 );
19534
19535 my @Dirs = (
19536 "private",
19537 "priv",
19538 "port",
19539 "impl",
19540 "internal",
19541 "detail",
19542 "details",
19543 "old",
19544 "compat",
19545 "debug",
19546 "config",
19547 "compiler",
19548 "platform",
19549 "test"
19550 );
19551
19552 if(my $TERMs = join("|", @Terms)) {
19553 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19554 }
19555 if(my $DIRs = join("|", @Dirs)) {
19556 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19557 }
19558
19559 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19560 }
19561
19562 if($Tolerance=~/1/)
19563 { # 1 - skip non-Linux headers
19564 if($OSgroup ne "windows")
19565 {
19566 if(specificHeader($Path, "windows")) {
19567 return 1;
19568 }
19569 }
19570 if($OSgroup ne "macos")
19571 {
19572 if(specificHeader($Path, "macos")) {
19573 return 1;
19574 }
19575 }
19576 }
19577
19578 # valid
19579 return 0;
19580}
19581
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019582sub skipHeader($$)
19583{
19584 my ($Path, $LibVersion) = @_;
19585 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019586 if(defined $Cache{"skipHeader"}{$Path}) {
19587 return $Cache{"skipHeader"}{$Path};
19588 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019589 if(defined $Tolerance and $Tolerance=~/1|2/)
19590 { # --tolerant
19591 if(skipAlienHeader($Path)) {
19592 return ($Cache{"skipHeader"}{$Path} = 1);
19593 }
19594 }
19595 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19596 return 0;
19597 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019598 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19599}
19600
19601sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019602{ # returns:
19603 # 1 - if header should NOT be included and checked
19604 # 2 - if header should NOT be included, but should be checked
19605 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019606 my $Name = get_filename($Path);
19607 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019608 return $Kind;
19609 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019610 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19611 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019612 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019613 if(index($Path, $D)!=-1)
19614 {
19615 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19616 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019618 }
19619 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019620 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19621 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019622 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019623 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19624 {
19625 if($Name=~/$P/) {
19626 return $Kind;
19627 }
19628 if($P=~/[\/\\]/ and $Path=~/$P/) {
19629 return $Kind;
19630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631 }
19632 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019633
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019634 return 0;
19635}
19636
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019637sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019638{
19639 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019640 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019641 { # system directory
19642 return;
19643 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019644 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019645 { # already registered
19646 return;
19647 }
19648 foreach my $Path (find_libs($Dir,"",1))
19649 {
19650 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019651 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019652 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019653 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019654 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19655}
19656
19657sub registerObject($$)
19658{
19659 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019660
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019661 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019662 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019663 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019664 {
19665 if(my $SONAME = getSONAME($Path)) {
19666 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19667 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019668 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019669 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19670 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019671 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019672
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019673 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019674 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019675 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019676 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019677 if($ObjArch ne getArch_GCC($LibVersion))
19678 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19679 $CheckedArch{$LibVersion} = 1;
19680 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 +040019681 }
19682 }
19683 }
19684}
19685
19686sub getArch_Object($)
19687{
19688 my $Path = $_[0];
19689
19690 my %MachineType = (
19691 "14C" => "x86",
19692 "8664" => "x86_64",
19693 "1C0" => "arm",
19694 "200" => "ia64"
19695 );
19696
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019697 my %ArchName = (
19698 "s390:31-bit" => "s390",
19699 "s390:64-bit" => "s390x",
19700 "powerpc:common" => "ppc32",
19701 "powerpc:common64" => "ppc64",
19702 "i386:x86-64" => "x86_64",
19703 "mips:3000" => "mips",
19704 "sparc:v8plus" => "sparcv9"
19705 );
19706
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019707 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019708 {
19709 my $DumpbinCmd = get_CmdPath("dumpbin");
19710 if(not $DumpbinCmd) {
19711 exitStatus("Not_Found", "can't find \"dumpbin\"");
19712 }
19713
19714 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19715 my $Out = `$Cmd`;
19716
19717 if($Out=~/(\w+)\smachine/)
19718 {
19719 if(my $Type = $MachineType{uc($1)})
19720 {
19721 return $Type;
19722 }
19723 }
19724 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019725 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019726 {
19727 my $ObjdumpCmd = get_CmdPath("objdump");
19728 if(not $ObjdumpCmd) {
19729 exitStatus("Not_Found", "can't find \"objdump\"");
19730 }
19731
19732 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019733
19734 if($OSgroup eq "windows") {
19735 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19736 }
19737 else {
19738 $Cmd = "LANG=$LOCALE ".$Cmd;
19739 }
19740 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019741
19742 if($Out=~/architecture:\s+([\w\-\:]+)/)
19743 {
19744 my $Arch = $1;
19745 if($Arch=~s/\:(.+)//)
19746 {
19747 my $Suffix = $1;
19748
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019749 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019750 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019751 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019752 }
19753 }
19754
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019755 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019756 $Arch = "x86";
19757 }
19758
19759 if($Arch eq "x86-64") {
19760 $Arch = "x86_64";
19761 }
19762
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019763 if($Arch eq "ia64-elf64") {
19764 $Arch = "ia64";
19765 }
19766
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019767 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019768 }
19769 }
19770 else
19771 { # macos, etc.
19772 # TODO
19773 }
19774
19775 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019776}
19777
19778sub getSONAME($)
19779{
19780 my $Path = $_[0];
19781 return if(not $Path);
19782 if(defined $Cache{"getSONAME"}{$Path}) {
19783 return $Cache{"getSONAME"}{$Path};
19784 }
19785 my $ObjdumpCmd = get_CmdPath("objdump");
19786 if(not $ObjdumpCmd) {
19787 exitStatus("Not_Found", "can't find \"objdump\"");
19788 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019789 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019790 if($OSgroup eq "windows") {
19791 $SonameCmd .= " | find \"SONAME\"";
19792 }
19793 else {
19794 $SonameCmd .= " | grep SONAME";
19795 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019796 if(my $SonameInfo = `$SonameCmd`)
19797 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019798 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19799 return ($Cache{"getSONAME"}{$Path} = $1);
19800 }
19801 }
19802 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019803}
19804
19805sub getSOPaths_Dest($$)
19806{
19807 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019808 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019809 return ();
19810 }
19811 if(-f $Dest)
19812 {
19813 if(not parse_libname($Dest, "name", $OStarget)) {
19814 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19815 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019816 registerObject($Dest, $LibVersion);
19817 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 return ($Dest);
19819 }
19820 elsif(-d $Dest)
19821 {
19822 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019823 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019824 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019825 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19826 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019827 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019828 { # all files and symlinks that match the name of a library
19829 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19830 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019831 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019832 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019833 }
19834 }
19835 }
19836 else
19837 { # search for all files and symlinks
19838 foreach my $Path (find_libs($Dest,"",""))
19839 {
19840 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019841 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019842 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019843 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019844 }
19845 if($OSgroup eq "macos")
19846 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019847 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019848 {
19849 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019850 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019851 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019852 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19853 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019854 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019855 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019856 }
19857 }
19858 }
19859 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019860 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019861 }
19862 else {
19863 return ();
19864 }
19865}
19866
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019867sub isCyclical($$)
19868{
19869 my ($Stack, $Value) = @_;
19870 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019871}
19872
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019873sub getGCC_Opts($)
19874{ # to use in module
19875 my $LibVersion = $_[0];
19876
19877 my @Opts = ();
19878
19879 if($CompilerOptions{$LibVersion})
19880 { # user-defined options
19881 push(@Opts, $CompilerOptions{$LibVersion});
19882 }
19883 if($GccOptions)
19884 { # additional
19885 push(@Opts, $GccOptions);
19886 }
19887
19888 if(@Opts) {
19889 return join(" ", @Opts);
19890 }
19891
19892 return undef;
19893}
19894
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019895sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019896{
19897 my $LibVersion = $_[0];
19898
19899 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19900 return $Cache{"getArch_GCC"}{$LibVersion};
19901 }
19902
19903 my $Arch = undef;
19904
19905 if($GCC_PATH)
19906 {
19907 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19908
19909 my $Cmd = $GCC_PATH." test.c -o test";
19910 if(my $Opts = getGCC_Opts($LibVersion))
19911 { # user-defined options
19912 $Cmd .= " ".$Opts;
19913 }
19914
19915 chdir($TMP_DIR);
19916 system($Cmd);
19917 chdir($ORIG_DIR);
19918
19919 $Arch = getArch_Object("$TMP_DIR/test");
19920
19921 unlink("$TMP_DIR/test.c");
19922 unlink("$TMP_DIR/test");
19923 }
19924
19925 if(not $Arch) {
19926 exitStatus("Error", "can't check ARCH type");
19927 }
19928
19929 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19930}
19931
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019932sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019933{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019934 my $LibVersion = $_[0];
19935
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019936 my $Size = undef;
19937
19938 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019939 if(my $Arch = getArch($LibVersion))
19940 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019941 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019942 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019943 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019944 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19945 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019946 }
19947 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019948
19949 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019950 {
19951 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019952
19953 my $Cmd = $GCC_PATH." -E -dD empty.h";
19954 if(my $Opts = getGCC_Opts($LibVersion))
19955 { # user-defined options
19956 $Cmd .= " ".$Opts;
19957 }
19958
19959 chdir($TMP_DIR);
19960 my $Defines = `$Cmd`;
19961 chdir($ORIG_DIR);
19962
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019963 unlink("$TMP_DIR/empty.h");
19964
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019965 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19966 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019967 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019968 }
19969 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19970 { # GCC 3
19971 my $PTRDIFF = $1;
19972 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019973 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019974 }
19975 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019976 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019977 }
19978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019979 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019980
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019981 if(not $Size) {
19982 exitStatus("Error", "can't check WORD size");
19983 }
19984
19985 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019986}
19987
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019988sub getWordSize($)
19989{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019990 return $WORD_SIZE{$_[0]};
19991}
19992
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019993sub majorVersion($)
19994{
19995 my $V = $_[0];
19996 return 0 if(not $V);
19997 my @VParts = split(/\./, $V);
19998 return $VParts[0];
19999}
20000
20001sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020002{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020003 my ($V1, $V2) = @_;
20004 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020005 my @V1Parts = split(/\./, $V1);
20006 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020007 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20008 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020009 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20010 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20011 }
20012 return -1 if($#V1Parts < $#V2Parts);
20013 return 1 if($#V1Parts > $#V2Parts);
20014 return 0;
20015}
20016
20017sub read_ABI_Dump($$)
20018{
20019 my ($LibVersion, $Path) = @_;
20020 return if(not $LibVersion or not -e $Path);
20021 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020022 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020023 { # input *.abi
20024 $FilePath = $Path;
20025 }
20026 else
20027 { # input *.abi.tar.gz
20028 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020029 if(not isDump_U($FilePath)) {
20030 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020032 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020033
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020034 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020035
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020036 my $Line = readLineNum($FilePath, 0);
20037 if($Line=~/xml/)
20038 { # XML format
20039 loadModule("XmlDump");
20040 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020041 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020042 else
20043 { # Perl Data::Dumper format (default)
20044 open(DUMP, $FilePath);
20045 local $/ = undef;
20046 my $Content = <DUMP>;
20047 close(DUMP);
20048
20049 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20050 { # remove temp file
20051 unlink($FilePath);
20052 }
20053 if($Content!~/};\s*\Z/) {
20054 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20055 }
20056 $ABI = eval($Content);
20057 if(not $ABI) {
20058 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020060 }
20061 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020062 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020063 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020064 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020066 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020067 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020068 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020069 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020070
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020071 if($ABI->{"PublicABI"}) {
20072 $UsedDump{$LibVersion}{"Public"} = 1;
20073 }
20074
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020075 if($ABI->{"ABI_DUMP_VERSION"})
20076 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020077 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020078 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020079 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020080 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020081 }
20082 else
20083 { # support for old ABI dumps
20084 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020085 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020086 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020087 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020088 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020089
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020090 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020091 {
20092 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 +040020093 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020094
20095 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20096 { # DWARF ABI Dump
20097 $UseConv_Real{$LibVersion}{"P"} = 1;
20098 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20099
20100 $UsedDump{$LibVersion}{"DWARF"} = 1;
20101
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020102 if(not $TargetComponent_Opt)
20103 {
20104 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20105 $TargetComponent = "module";
20106 }
20107 else {
20108 $TargetComponent = "object";
20109 }
20110 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020111 }
20112
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020113 if(not checkDump($LibVersion, "2.11"))
20114 { # old ABI dumps
20115 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020116 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020117 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020118 { # ABI dump created with --binary option
20119 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20120 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020121 else
20122 { # default
20123 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20124 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020125
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020126 if(defined $ABI->{"Mode"}
20127 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020128 { # --ext option
20129 $ExtendedCheck = 1;
20130 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020131 if($ABI->{"Extra"}) {
20132 $ExtraDump = 1;
20133 }
20134
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020135 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020136 {
20137 $UsedDump{$LibVersion}{"L"} = $Lang;
20138 setLanguage($LibVersion, $Lang);
20139 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020140 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020141 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020142 }
20143 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020144 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020145 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020146 if(not $TInfo)
20147 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020148 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020149 }
20150 my %Tid_TDid = ();
20151 foreach my $TDid (keys(%{$TInfo}))
20152 {
20153 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20154 {
20155 $MAX_ID = $Tid if($Tid>$MAX_ID);
20156 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020157 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020158 }
20159 }
20160 my %NewID = ();
20161 foreach my $Tid (keys(%Tid_TDid))
20162 {
20163 my @TDids = keys(%{$Tid_TDid{$Tid}});
20164 if($#TDids>=1)
20165 {
20166 foreach my $TDid (@TDids)
20167 {
20168 if($TDid) {
20169 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20170 }
20171 else
20172 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020173 my $ID = ++$MAX_ID;
20174
20175 $NewID{$TDid}{$Tid} = $ID;
20176 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20177 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020178 }
20179 }
20180 }
20181 else
20182 {
20183 my $TDid = $TDids[0];
20184 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20185 }
20186 }
20187 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20188 {
20189 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20190 if(defined $Info{"BaseType"})
20191 {
20192 my $Bid = $Info{"BaseType"}{"Tid"};
20193 my $BDid = $Info{"BaseType"}{"TDid"};
20194 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020195 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020196 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20197 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20198 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020199 }
20200 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020202 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020203 read_Machine_DumpInfo($ABI, $LibVersion);
20204 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020205 if(not $SymbolInfo{$LibVersion})
20206 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020207 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020208 }
20209 if(not keys(%{$SymbolInfo{$LibVersion}}))
20210 { # validation of old-version dumps
20211 if(not $ExtendedCheck) {
20212 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20213 }
20214 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020215 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020216 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020217 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020218 else
20219 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020220 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020221 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020222 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020223 }
20224 if(not $DepSymbols)
20225 { # Cannot reconstruct DepSymbols. This may result in false
20226 # positives if the old dump is for library 2. Not a problem if
20227 # old dumps are only from old libraries.
20228 $DepSymbols = {};
20229 }
20230 foreach my $Symbol (keys(%{$DepSymbols})) {
20231 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020233 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020234 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020235
20236 if(my $V = $TargetVersion{$LibVersion}) {
20237 $Descriptor{$LibVersion}{"Version"} = $V;
20238 }
20239 else {
20240 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20241 }
20242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020243 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020244 { # if not defined by -skip-types option
20245 if(defined $ABI->{"SkipTypes"})
20246 {
20247 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20248 {
20249 $SkipTypes{$LibVersion}{$TName} = 1;
20250 }
20251 }
20252 if(defined $ABI->{"OpaqueTypes"})
20253 { # support for old dumps
20254 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20255 {
20256 $SkipTypes{$LibVersion}{$TName} = 1;
20257 }
20258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020259 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020260
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020261 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020262 { # if not defined by -skip-symbols option
20263 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20264 if(not $SkipSymbols{$LibVersion})
20265 { # support for old dumps
20266 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20267 }
20268 if(not $SkipSymbols{$LibVersion})
20269 { # support for old dumps
20270 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020272 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020273 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020274
20275 if(not $TargetHeaders{$LibVersion})
20276 { # if not defined by -headers-list option
20277 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20278 }
20279
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020280 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020281 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020282 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020283 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020284 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020285 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020286
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020287 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020288 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020289
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020290 if(not checkDump($LibVersion, "2.10.1")
20291 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020292 { # support for old ABI dumps: added target headers
20293 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020294 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020295 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020296
20297 if(not $ABI->{"PublicABI"})
20298 {
20299 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20300 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20301 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020303 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020304 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020305 if(defined $ABI->{"GccConstants"})
20306 { # 3.0
20307 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20308 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20309 }
20310 }
20311
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020312 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020313 if(not $NestedNameSpaces{$LibVersion})
20314 { # support for old dumps
20315 # Cannot reconstruct NameSpaces. This may affect design
20316 # of the compatibility report.
20317 $NestedNameSpaces{$LibVersion} = {};
20318 }
20319 # target system type
20320 # needed to adopt HTML report
20321 if(not $DumpSystem)
20322 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020323 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020324 }
20325 # recreate environment
20326 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20327 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020328 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020330 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20331 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020332 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020333 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020334 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020335 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20336 {
20337 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20338 setLanguage($LibVersion, "C++");
20339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020340 }
20341 }
20342 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020343 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20344 {
20345 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20346 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20347 }
20348 }
20349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020350 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020351 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020352 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020353 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020354 {
20355 if(not $Symbol_Library{$LibVersion}{$MnglName}
20356 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20357 push(@VFunc, $MnglName);
20358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020359 }
20360 }
20361 translateSymbols(@VFunc, $LibVersion);
20362 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020363 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20364
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020365 if(not checkDump($LibVersion, "3.0"))
20366 { # support for old ABI dumps
20367 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20368 {
20369 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20370 {
20371 if(ref($BaseType) eq "HASH") {
20372 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20373 }
20374 }
20375 }
20376 }
20377
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020378 if(not checkDump($LibVersion, "3.2"))
20379 { # support for old ABI dumps
20380 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20381 {
20382 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20383 {
20384 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20385 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20386 }
20387 }
20388 }
20389
20390 # repair target headers list
20391 delete($TargetHeaders{$LibVersion});
20392 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020393 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20394 }
20395 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20396 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020397 }
20398
20399 # non-target constants from anon enums
20400 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20401 {
20402 if(not $ExtraDump
20403 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20404 {
20405 delete($Constants{$LibVersion}{$Name});
20406 }
20407 }
20408 }
20409
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020410 if(not checkDump($LibVersion, "2.20"))
20411 { # support for old ABI dumps
20412 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20413 {
20414 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20415
20416 if($TType=~/Struct|Union|Enum|Typedef/)
20417 { # repair complex types first
20418 next;
20419 }
20420
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020421 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020422 {
20423 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20424 if($BType=~/Struct|Union|Enum/i)
20425 {
20426 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20427 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20428 }
20429 }
20430 }
20431 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20432 {
20433 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20434 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20435 if($TType=~/Struct|Union|Enum/) {
20436 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20437 }
20438 }
20439 }
20440
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020441 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020442 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020443 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20444 { # support for old ABI dumps < 2.0 (ACC 1.22)
20445 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20446 {
20447 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20448 {
20449 if($Access ne "public") {
20450 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20451 }
20452 }
20453 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20454 }
20455 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20456 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020457 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20458 { # support for old ABI dumps
20459 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20460 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020461 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20462 { # DWARF ABI Dumps
20463 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20464 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020465 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20466 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20467 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020468
20469 # support for old formatting of type names
20470 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20471
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020472 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20473 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020474 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020475 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20476 {
20477 if($SubId eq $TypeId)
20478 { # Fix erroneus ABI dump
20479 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20480 next;
20481 }
20482
20483 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020484 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020485 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020486 if($TInfo{"Type"} eq "MethodPtr")
20487 {
20488 if(defined $TInfo{"Param"})
20489 { # support for old ABI dumps <= 1.17
20490 if(not defined $TInfo{"Param"}{"0"})
20491 {
20492 my $Max = keys(%{$TInfo{"Param"}});
20493 foreach my $Pos (1 .. $Max) {
20494 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20495 }
20496 delete($TInfo{"Param"}{$Max});
20497 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20498 }
20499 }
20500 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020501 if($TInfo{"BaseType"} eq $TypeId)
20502 { # fix ABI dump
20503 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20504 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020505
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020506 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020507 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020508 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020510 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20511 if(not $BName)
20512 { # broken type
20513 next;
20514 }
20515 if($TInfo{"Name"} eq $BName)
20516 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020517 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020518 next;
20519 }
20520 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20521 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020522 }
20523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020524 }
20525 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20526 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020527 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020528 }
20529 }
20530
20531 if(not checkDump($LibVersion, "2.15"))
20532 { # support for old ABI dumps
20533 my %Dups = ();
20534 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20535 {
20536 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020537 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020538 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20539 { # remove template decls
20540 delete($SymbolInfo{$LibVersion}{$InfoId});
20541 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020543 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020544 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20545 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020546 { # templates
20547 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020548 }
20549 }
20550 }
20551
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020552 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20553 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020554 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20555 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20556 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20557 { # support for old ABI dumps (< 3.1)
20558 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20559 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20560 { # add "this" first parameter
20561 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20562 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20563
20564 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20565 {
20566 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20567 foreach my $Pos (reverse(0 .. $#Pos)) {
20568 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20569 }
20570 }
20571 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20572 }
20573 }
20574
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020575 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20576 { # ABI dumps have no mangled names for C-functions
20577 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20578 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020579 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20580 { # support for old ABI dumps
20581 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20582 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020583 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20584 { # DWARF ABI Dumps
20585 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20586 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020587 }
20588
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020589 $Descriptor{$LibVersion}{"Dump"} = 1;
20590}
20591
20592sub read_Machine_DumpInfo($$)
20593{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020594 my ($ABI, $LibVersion) = @_;
20595 if($ABI->{"Arch"}) {
20596 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020597 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020598 if($ABI->{"WordSize"}) {
20599 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020600 }
20601 else
20602 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020603 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020604 }
20605 if(not $WORD_SIZE{$LibVersion})
20606 { # support for old dumps (<1.23)
20607 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20608 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020609 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020610 }
20611 else
20612 {
20613 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020614 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020615 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020616 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20617 { # any "pointer"-type
20618 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020619 last;
20620 }
20621 }
20622 if($PSize)
20623 { # a pointer type size
20624 $WORD_SIZE{$LibVersion} = $PSize;
20625 }
20626 else {
20627 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20628 }
20629 }
20630 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020631 if($ABI->{"GccVersion"}) {
20632 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020633 }
20634}
20635
20636sub read_Libs_DumpInfo($$)
20637{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020638 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020639 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20640 if(not $Library_Symbol{$LibVersion})
20641 { # support for old dumps
20642 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020644 if(keys(%{$Library_Symbol{$LibVersion}})
20645 and not $DumpAPI) {
20646 $Descriptor{$LibVersion}{"Libs"} = "OK";
20647 }
20648}
20649
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020650sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020651{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020652 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020653
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020654 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020655 and not $DumpAPI) {
20656 $Descriptor{$LibVersion}{"Headers"} = "OK";
20657 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020658 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020659 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020660 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020661 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020662 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020663
20664 if(keys(%{$ABI->{"Sources"}})
20665 and not $DumpAPI) {
20666 $Descriptor{$LibVersion}{"Sources"} = "OK";
20667 }
20668 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020669 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020670 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20671 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020673}
20674
20675sub find_libs($$$)
20676{
20677 my ($Path, $Type, $MaxDepth) = @_;
20678 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020679 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020680}
20681
20682sub createDescriptor($$)
20683{
20684 my ($LibVersion, $Path) = @_;
20685 if(not $LibVersion or not $Path
20686 or not -e $Path) {
20687 return "";
20688 }
20689 if(-d $Path)
20690 { # directory with headers files and shared objects
20691 return "
20692 <version>
20693 ".$TargetVersion{$LibVersion}."
20694 </version>
20695
20696 <headers>
20697 $Path
20698 </headers>
20699
20700 <libs>
20701 $Path
20702 </libs>";
20703 }
20704 else
20705 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020706 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020707 { # standard XML-descriptor
20708 return readFile($Path);
20709 }
20710 elsif(is_header($Path, 2, $LibVersion))
20711 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020712 $CheckHeadersOnly = 1;
20713
20714 if($LibVersion==1) {
20715 $TargetVersion{$LibVersion} = "X";
20716 }
20717
20718 if($LibVersion==2) {
20719 $TargetVersion{$LibVersion} = "Y";
20720 }
20721
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020722 return "
20723 <version>
20724 ".$TargetVersion{$LibVersion}."
20725 </version>
20726
20727 <headers>
20728 $Path
20729 </headers>
20730
20731 <libs>
20732 none
20733 </libs>";
20734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020735 else
20736 { # standard XML-descriptor
20737 return readFile($Path);
20738 }
20739 }
20740}
20741
20742sub detect_lib_default_paths()
20743{
20744 my %LPaths = ();
20745 if($OSgroup eq "bsd")
20746 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020747 if(my $LdConfig = get_CmdPath("ldconfig"))
20748 {
20749 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20750 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020751 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20752 {
20753 my $Name = "lib".$1;
20754 if(not defined $LPaths{$Name}) {
20755 $LPaths{$Name} = $2;
20756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020757 }
20758 }
20759 }
20760 else {
20761 printMsg("WARNING", "can't find ldconfig");
20762 }
20763 }
20764 else
20765 {
20766 if(my $LdConfig = get_CmdPath("ldconfig"))
20767 {
20768 if($SystemRoot and $OSgroup eq "linux")
20769 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20770 if(-e $SystemRoot."/etc/ld.so.conf") {
20771 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20772 }
20773 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020774 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20775 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020776 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20777 {
20778 my ($Name, $Path) = ($1, $2);
20779 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020780 if(not defined $LPaths{$Name})
20781 { # get first element from the list of available paths
20782
20783 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20784 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20785 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20786
20787 $LPaths{$Name} = $Path;
20788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020789 }
20790 }
20791 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020792 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020793 printMsg("WARNING", "can't find ldconfig");
20794 }
20795 }
20796 return \%LPaths;
20797}
20798
20799sub detect_bin_default_paths()
20800{
20801 my $EnvPaths = $ENV{"PATH"};
20802 if($OSgroup eq "beos") {
20803 $EnvPaths.=":".$ENV{"BETOOLS"};
20804 }
20805 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020806 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020807 {
20808 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020809 next if(not $Path);
20810 if($SystemRoot
20811 and $Path=~/\A\Q$SystemRoot\E\//)
20812 { # do NOT use binaries from target system
20813 next;
20814 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020815 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020816 }
20817}
20818
20819sub detect_inc_default_paths()
20820{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020821 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020822 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020823 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020824 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020825 next if(index($Line, "/cc1plus ")!=-1);
20826
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020827 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20828 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020829 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020831 if(index($Path, "c++")!=-1
20832 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020833 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020834 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020835 if(not defined $MAIN_CPP_DIR
20836 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20837 $MAIN_CPP_DIR = $Path;
20838 }
20839 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020840 elsif(index($Path, "gcc")!=-1) {
20841 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020842 }
20843 else
20844 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020845 if($Path=~/local[\/\\]+include/)
20846 { # local paths
20847 next;
20848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020849 if($SystemRoot
20850 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20851 { # The GCC include path for user headers is not a part of the system root
20852 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20853 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20854 next;
20855 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020856 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020857 }
20858 }
20859 }
20860 unlink("$TMP_DIR/empty.h");
20861 return %DPaths;
20862}
20863
20864sub detect_default_paths($)
20865{
20866 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20867 my $Search = $_[0];
20868 if($Search!~/inc/) {
20869 $HSearch = 0;
20870 }
20871 if($Search!~/lib/) {
20872 $LSearch = 0;
20873 }
20874 if($Search!~/bin/) {
20875 $BSearch = 0;
20876 }
20877 if($Search!~/gcc/) {
20878 $GSearch = 0;
20879 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020880 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020881 { # <search_headers> section of the XML descriptor
20882 # do NOT search for systems headers
20883 $HSearch = 0;
20884 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020885 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020886 { # <search_libs> section of the XML descriptor
20887 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020888 $LSearch = 0;
20889 }
20890 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20891 { # additional search paths
20892 next if($Type eq "include" and not $HSearch);
20893 next if($Type eq "lib" and not $LSearch);
20894 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020895 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020896 }
20897 if($OSgroup ne "windows")
20898 { # unix-like
20899 foreach my $Type ("include", "lib", "bin")
20900 { # automatic detection of system "devel" directories
20901 next if($Type eq "include" and not $HSearch);
20902 next if($Type eq "lib" and not $LSearch);
20903 next if($Type eq "bin" and not $BSearch);
20904 my ($UsrDir, $RootDir) = ("/usr", "/");
20905 if($SystemRoot and $Type ne "bin")
20906 { # 1. search for target headers and libraries
20907 # 2. use host commands: ldconfig, readelf, etc.
20908 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20909 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020910 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020911 if(-d $RootDir."/".$Type)
20912 { # if "/lib" is symbolic link
20913 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020914 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020915 }
20916 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020917 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020918 }
20919 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020920 if(-d $UsrDir)
20921 {
20922 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020923 if(-d $UsrDir."/".$Type)
20924 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020925 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020926 }
20927 }
20928 }
20929 }
20930 if($BSearch)
20931 {
20932 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020933 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020934 }
20935 # check environment variables
20936 if($OSgroup eq "beos")
20937 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020938 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020939 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020940 if($_ eq ".") {
20941 next;
20942 }
20943 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20944 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20945 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020946 }
20947 }
20948 if($HSearch)
20949 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020950 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20951 split(/:|;/, $ENV{"BEINCLUDES"})
20952 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953 }
20954 if($LSearch)
20955 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020956 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20957 split(/:|;/, $ENV{"BELIBRARIES"}),
20958 split(/:|;/, $ENV{"LIBRARY_PATH"})
20959 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020960 }
20961 }
20962 if($LSearch)
20963 { # using linker to get system paths
20964 if(my $LPaths = detect_lib_default_paths())
20965 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020966 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020967 foreach my $Name (keys(%{$LPaths}))
20968 {
20969 if($SystemRoot
20970 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20971 { # wrong ldconfig configuration
20972 # check your <sysroot>/etc/ld.so.conf
20973 next;
20974 }
20975 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020976 if(my $Dir = get_dirname($LPaths->{$Name})) {
20977 $Dirs{$Dir} = 1;
20978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020979 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020980 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020981 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020982 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020983 }
20984 if($BSearch)
20985 {
20986 if($CrossGcc)
20987 { # --cross-gcc=arm-linux-gcc
20988 if(-e $CrossGcc)
20989 { # absolute or relative path
20990 $GCC_PATH = get_abs_path($CrossGcc);
20991 }
20992 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20993 { # command name
20994 $GCC_PATH = $CrossGcc;
20995 }
20996 else {
20997 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20998 }
20999 if($GCC_PATH=~/\s/) {
21000 $GCC_PATH = "\"".$GCC_PATH."\"";
21001 }
21002 }
21003 }
21004 if($GSearch)
21005 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021006 if(not $CrossGcc)
21007 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021008 $GCC_PATH = get_CmdPath("gcc");
21009 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021010 if(not $GCC_PATH)
21011 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021012 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021013 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021014 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021015 { # select the latest version
21016 @GCCs = sort {$b cmp $a} @GCCs;
21017 if(check_gcc($GCCs[0], "3"))
21018 {
21019 $GCC_PATH = $GCCs[0];
21020 last;
21021 }
21022 }
21023 }
21024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021025 if(not $GCC_PATH) {
21026 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21027 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021028
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021029 my $GCC_Ver = get_dumpversion($GCC_PATH);
21030 if($GCC_Ver eq "4.8")
21031 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21032 my $Info = `$GCC_PATH --version`;
21033
21034 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21035 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21036 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21037 $GCC_Ver = $2;
21038 }
21039 }
21040
21041 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021043 my $GccTarget = get_dumpmachine($GCC_PATH);
21044
21045 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021046 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021047 $OStarget = "linux";
21048 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021049 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021050 elsif($GccTarget=~/symbian/)
21051 {
21052 $OStarget = "symbian";
21053 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21054 }
21055
21056 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21057
21058 # check GCC version
21059 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21060 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021061 # introduced in 4.8 and fixed in 4.8.3
21062 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.");
21063
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021064 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021065 }
21066 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021067 else {
21068 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021069 }
21070 }
21071 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021072 {
21073 # GCC standard paths
21074 if($GCC_PATH and not $NoStdInc)
21075 {
21076 my %DPaths = detect_inc_default_paths();
21077 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21078 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21079 @DefaultIncPaths = @{$DPaths{"Inc"}};
21080 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21081 }
21082
21083 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021084 my $IncPath = "/usr/include";
21085 if($SystemRoot) {
21086 $IncPath = $SystemRoot.$IncPath;
21087 }
21088 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021089 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021090 }
21091 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021092
21093 if($ExtraInfo)
21094 {
21095 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21096 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021098}
21099
21100sub getLIB_EXT($)
21101{
21102 my $Target = $_[0];
21103 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21104 return $Ext;
21105 }
21106 return $OS_LibExt{$LIB_TYPE}{"default"};
21107}
21108
21109sub getAR_EXT($)
21110{
21111 my $Target = $_[0];
21112 if(my $Ext = $OS_Archive{$Target}) {
21113 return $Ext;
21114 }
21115 return $OS_Archive{"default"};
21116}
21117
21118sub get_dumpversion($)
21119{
21120 my $Cmd = $_[0];
21121 return "" if(not $Cmd);
21122 if($Cache{"get_dumpversion"}{$Cmd}) {
21123 return $Cache{"get_dumpversion"}{$Cmd};
21124 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021125 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021126 chomp($V);
21127 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21128}
21129
21130sub get_dumpmachine($)
21131{
21132 my $Cmd = $_[0];
21133 return "" if(not $Cmd);
21134 if($Cache{"get_dumpmachine"}{$Cmd}) {
21135 return $Cache{"get_dumpmachine"}{$Cmd};
21136 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021137 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021138 chomp($Machine);
21139 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21140}
21141
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021142sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143{
21144 my $Cmd = $_[0];
21145 return "" if(not $Cmd);
21146 my @Options = (
21147 "--version",
21148 "-help"
21149 );
21150 foreach my $Opt (@Options)
21151 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021152 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021153 if($Info) {
21154 return 1;
21155 }
21156 }
21157 return 0;
21158}
21159
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021160sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021161{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021162 my ($Cmd, $ReqVer) = @_;
21163 return 0 if(not $Cmd or not $ReqVer);
21164 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21165 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021166 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021167 if(my $GccVer = get_dumpversion($Cmd))
21168 {
21169 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21170 if(cmpVersions($GccVer, $ReqVer)>=0) {
21171 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21172 }
21173 }
21174 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021175}
21176
21177sub get_depth($)
21178{
21179 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021180 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021181 }
21182 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21183}
21184
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021185sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021186{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021187 return if($Cache{"registerGccHeaders"}); # this function should be called once
21188
21189 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021190 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021191 my @Headers = cmd_find($Path,"f");
21192 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21193 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021194 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021195 my $FileName = get_filename($HPath);
21196 if(not defined $DefaultGccHeader{$FileName})
21197 { # skip duplicated
21198 $DefaultGccHeader{$FileName} = $HPath;
21199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021200 }
21201 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021202 $Cache{"registerGccHeaders"} = 1;
21203}
21204
21205sub registerCppHeaders()
21206{
21207 return if($Cache{"registerCppHeaders"}); # this function should be called once
21208
21209 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021210 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021211 my @Headers = cmd_find($CppDir,"f");
21212 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21213 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021214 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021215 my $FileName = get_filename($Path);
21216 if(not defined $DefaultCppHeader{$FileName})
21217 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021218 $DefaultCppHeader{$FileName} = $Path;
21219 }
21220 }
21221 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021222 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021223}
21224
21225sub parse_libname($$$)
21226{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021227 return "" if(not $_[0]);
21228 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21229 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021230 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021231 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21232}
21233
21234sub parse_libname_I($$$)
21235{
21236 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021238 if($Target eq "symbian") {
21239 return parse_libname_symbian($Name, $Type);
21240 }
21241 elsif($Target eq "windows") {
21242 return parse_libname_windows($Name, $Type);
21243 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021244
21245 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021246 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021247 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021248 { # libSDL-1.2.so.0.7.1
21249 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021250 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021251 if($Type eq "name")
21252 { # libSDL-1.2
21253 # libwbxml2
21254 return $2;
21255 }
21256 elsif($Type eq "name+ext")
21257 { # libSDL-1.2.so
21258 # libwbxml2.so
21259 return $1;
21260 }
21261 elsif($Type eq "version")
21262 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021263 if(defined $7
21264 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021265 { # 0.7.1
21266 return $7;
21267 }
21268 else
21269 { # libc-2.5.so (=>2.5 version)
21270 my $MV = $5;
21271 $MV=~s/\A[\-\_]+//g;
21272 return $MV;
21273 }
21274 }
21275 elsif($Type eq "short")
21276 { # libSDL
21277 # libwbxml2
21278 return $3;
21279 }
21280 elsif($Type eq "shortest")
21281 { # SDL
21282 # wbxml
21283 return shortest_name($3);
21284 }
21285 }
21286 return "";# error
21287}
21288
21289sub parse_libname_symbian($$)
21290{
21291 my ($Name, $Type) = @_;
21292 my $Ext = getLIB_EXT("symbian");
21293 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21294 { # libpthread{00010001}.dso
21295 if($Type eq "name")
21296 { # libpthread{00010001}
21297 return $2;
21298 }
21299 elsif($Type eq "name+ext")
21300 { # libpthread{00010001}.dso
21301 return $1;
21302 }
21303 elsif($Type eq "version")
21304 { # 00010001
21305 my $V = $4;
21306 $V=~s/\{(.+)\}/$1/;
21307 return $V;
21308 }
21309 elsif($Type eq "short")
21310 { # libpthread
21311 return $3;
21312 }
21313 elsif($Type eq "shortest")
21314 { # pthread
21315 return shortest_name($3);
21316 }
21317 }
21318 return "";# error
21319}
21320
21321sub parse_libname_windows($$)
21322{
21323 my ($Name, $Type) = @_;
21324 my $Ext = getLIB_EXT("windows");
21325 if($Name=~/((.+?)\.$Ext)\Z/)
21326 { # netapi32.dll
21327 if($Type eq "name")
21328 { # netapi32
21329 return $2;
21330 }
21331 elsif($Type eq "name+ext")
21332 { # netapi32.dll
21333 return $1;
21334 }
21335 elsif($Type eq "version")
21336 { # DLL version embedded
21337 # at binary-level
21338 return "";
21339 }
21340 elsif($Type eq "short")
21341 { # netapi32
21342 return $2;
21343 }
21344 elsif($Type eq "shortest")
21345 { # netapi
21346 return shortest_name($2);
21347 }
21348 }
21349 return "";# error
21350}
21351
21352sub shortest_name($)
21353{
21354 my $Name = $_[0];
21355 # remove prefix
21356 $Name=~s/\A(lib|open)//;
21357 # remove suffix
21358 $Name=~s/[\W\d_]+\Z//i;
21359 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21360 return $Name;
21361}
21362
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021363sub createSymbolsList($$$$$)
21364{
21365 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021367 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021368 prepareSymbols(1);
21369
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021370 my %SymbolHeaderLib = ();
21371 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021373 # Get List
21374 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21375 {
21376 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021377 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021378 next;
21379 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021380 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021381 { # skip other symbols
21382 next;
21383 }
21384 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21385 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021386 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021387 next;
21388 }
21389 my $DyLib = $Symbol_Library{1}{$Symbol};
21390 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021391 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021392 next;
21393 }
21394 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21395 $Total+=1;
21396 }
21397 # Draw List
21398 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21399 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21400 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21401 {
21402 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21403 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021404 my %NS_Symbol = ();
21405 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021406 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021407 }
21408 foreach my $NameSpace (sort keys(%NS_Symbol))
21409 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021410 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021411 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21412 foreach my $Symbol (@SortedInterfaces)
21413 {
21414 my $SubReport = "";
21415 my $Signature = get_Signature($Symbol, 1);
21416 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021417 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021418 }
21419 if($Symbol=~/\A(_Z|\?)/)
21420 {
21421 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021422 $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 +040021423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021424 else {
21425 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21426 }
21427 }
21428 else
21429 {
21430 if($Signature) {
21431 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21432 }
21433 else {
21434 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21435 }
21436 }
21437 $SYMBOLS_LIST .= $SubReport;
21438 }
21439 }
21440 $SYMBOLS_LIST .= "<br/>\n";
21441 }
21442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021443 # clear info
21444 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21445 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21446 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21447 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021448 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021449 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021450 my $CssStyles = readModule("Styles", "SymbolsList.css");
21451 my $JScripts = readModule("Scripts", "Sections.js");
21452 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021453 my $Title = "$LName: public symbols";
21454 my $Keywords = "$LName, API, symbols";
21455 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021456 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021457 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021458 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021459 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021460 writeFile($SaveTo, $SYMBOLS_LIST);
21461}
21462
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021463sub add_target_libs($)
21464{
21465 foreach (@{$_[0]}) {
21466 $TargetLibs{$_} = 1;
21467 }
21468}
21469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021470sub is_target_lib($)
21471{
21472 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021473 if(not $LName) {
21474 return 0;
21475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021476 if($TargetLibraryName
21477 and $LName!~/\Q$TargetLibraryName\E/) {
21478 return 0;
21479 }
21480 if(keys(%TargetLibs)
21481 and not $TargetLibs{$LName}
21482 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21483 return 0;
21484 }
21485 return 1;
21486}
21487
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021488sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021489{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021490 my ($H, $V) = @_;
21491 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021492 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021493 if($TargetHeaders{$V}{$H}) {
21494 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021495 }
21496 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021497 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021498}
21499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021500sub readLibs($)
21501{
21502 my $LibVersion = $_[0];
21503 if($OStarget eq "windows")
21504 { # dumpbin.exe will crash
21505 # without VS Environment
21506 check_win32_env();
21507 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021508 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021509 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021510 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021511}
21512
21513sub dump_sorting($)
21514{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021515 my $Hash = $_[0];
21516 return [] if(not $Hash);
21517 my @Keys = keys(%{$Hash});
21518 return [] if($#Keys<0);
21519 if($Keys[0]=~/\A\d+\Z/)
21520 { # numbers
21521 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021522 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021523 else
21524 { # strings
21525 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021526 }
21527}
21528
21529sub printMsg($$)
21530{
21531 my ($Type, $Msg) = @_;
21532 if($Type!~/\AINFO/) {
21533 $Msg = $Type.": ".$Msg;
21534 }
21535 if($Type!~/_C\Z/) {
21536 $Msg .= "\n";
21537 }
21538 if($Quiet)
21539 { # --quiet option
21540 appendFile($COMMON_LOG_PATH, $Msg);
21541 }
21542 else
21543 {
21544 if($Type eq "ERROR") {
21545 print STDERR $Msg;
21546 }
21547 else {
21548 print $Msg;
21549 }
21550 }
21551}
21552
21553sub exitStatus($$)
21554{
21555 my ($Code, $Msg) = @_;
21556 printMsg("ERROR", $Msg);
21557 exit($ERROR_CODE{$Code});
21558}
21559
21560sub exitReport()
21561{ # the tool has run without any errors
21562 printReport();
21563 if($COMPILE_ERRORS)
21564 { # errors in headers may add false positives/negatives
21565 exit($ERROR_CODE{"Compile_Error"});
21566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021567 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21568 { # --binary
21569 exit($ERROR_CODE{"Incompatible"});
21570 }
21571 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21572 { # --source
21573 exit($ERROR_CODE{"Incompatible"});
21574 }
21575 elsif($RESULT{"Source"}{"Problems"}
21576 or $RESULT{"Binary"}{"Problems"})
21577 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021578 exit($ERROR_CODE{"Incompatible"});
21579 }
21580 else {
21581 exit($ERROR_CODE{"Compatible"});
21582 }
21583}
21584
21585sub readRules($)
21586{
21587 my $Kind = $_[0];
21588 if(not -f $RULES_PATH{$Kind}) {
21589 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21590 }
21591 my $Content = readFile($RULES_PATH{$Kind});
21592 while(my $Rule = parseTag(\$Content, "rule"))
21593 {
21594 my $RId = parseTag(\$Rule, "id");
21595 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21596 foreach my $Prop (@Properties) {
21597 if(my $Value = parseTag(\$Rule, lc($Prop)))
21598 {
21599 $Value=~s/\n[ ]*//;
21600 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21601 }
21602 }
21603 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21604 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21605 }
21606 else {
21607 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21608 }
21609 }
21610}
21611
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021612sub getReportPath($)
21613{
21614 my $Level = $_[0];
21615 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21616 if($Level eq "Binary")
21617 {
21618 if($BinaryReportPath)
21619 { # --bin-report-path
21620 return $BinaryReportPath;
21621 }
21622 elsif($OutputReportPath)
21623 { # --report-path
21624 return $OutputReportPath;
21625 }
21626 else
21627 { # default
21628 return $Dir."/abi_compat_report.$ReportFormat";
21629 }
21630 }
21631 elsif($Level eq "Source")
21632 {
21633 if($SourceReportPath)
21634 { # --src-report-path
21635 return $SourceReportPath;
21636 }
21637 elsif($OutputReportPath)
21638 { # --report-path
21639 return $OutputReportPath;
21640 }
21641 else
21642 { # default
21643 return $Dir."/src_compat_report.$ReportFormat";
21644 }
21645 }
21646 else
21647 {
21648 if($OutputReportPath)
21649 { # --report-path
21650 return $OutputReportPath;
21651 }
21652 else
21653 { # default
21654 return $Dir."/compat_report.$ReportFormat";
21655 }
21656 }
21657}
21658
21659sub printStatMsg($)
21660{
21661 my $Level = $_[0];
21662 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21663}
21664
21665sub listAffected($)
21666{
21667 my $Level = $_[0];
21668 my $List = "";
21669 foreach (keys(%{$TotalAffected{$Level}}))
21670 {
21671 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21672 { # skip "Low"-severity problems
21673 next;
21674 }
21675 $List .= "$_\n";
21676 }
21677 my $Dir = get_dirname(getReportPath($Level));
21678 if($Level eq "Binary") {
21679 writeFile($Dir."/abi_affected.txt", $List);
21680 }
21681 elsif($Level eq "Source") {
21682 writeFile($Dir."/src_affected.txt", $List);
21683 }
21684}
21685
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021686sub printReport()
21687{
21688 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021689 createReport();
21690 if($JoinReport or $DoubleReport)
21691 {
21692 if($RESULT{"Binary"}{"Problems"}
21693 or $RESULT{"Source"}{"Problems"}) {
21694 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021695 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021696 else {
21697 printMsg("INFO", "result: COMPATIBLE");
21698 }
21699 printStatMsg("Binary");
21700 printStatMsg("Source");
21701 if($ListAffected)
21702 { # --list-affected
21703 listAffected("Binary");
21704 listAffected("Source");
21705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021707 elsif($BinaryOnly)
21708 {
21709 if($RESULT{"Binary"}{"Problems"}) {
21710 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21711 }
21712 else {
21713 printMsg("INFO", "result: COMPATIBLE");
21714 }
21715 printStatMsg("Binary");
21716 if($ListAffected)
21717 { # --list-affected
21718 listAffected("Binary");
21719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021720 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021721 elsif($SourceOnly)
21722 {
21723 if($RESULT{"Source"}{"Problems"}) {
21724 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21725 }
21726 else {
21727 printMsg("INFO", "result: COMPATIBLE");
21728 }
21729 printStatMsg("Source");
21730 if($ListAffected)
21731 { # --list-affected
21732 listAffected("Source");
21733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021734 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021735 if($StdOut)
21736 {
21737 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021738 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021739 printMsg("INFO", "compatibility report has been generated to stdout");
21740 }
21741 else
21742 { # default
21743 printMsg("INFO", "compatibility reports have been generated to stdout");
21744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021745 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021746 else
21747 {
21748 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021749 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021750 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21751 }
21752 elsif($DoubleReport)
21753 { # default
21754 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21755 }
21756 elsif($BinaryOnly)
21757 { # --binary
21758 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21759 }
21760 elsif($SourceOnly)
21761 { # --source
21762 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021764 }
21765}
21766
21767sub check_win32_env()
21768{
21769 if(not $ENV{"DevEnvDir"}
21770 or not $ENV{"LIB"}) {
21771 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21772 }
21773}
21774
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021775sub diffSets($$)
21776{
21777 my ($S1, $S2) = @_;
21778 my @SK1 = keys(%{$S1});
21779 my @SK2 = keys(%{$S2});
21780 if($#SK1!=$#SK2) {
21781 return 1;
21782 }
21783 foreach my $K1 (@SK1)
21784 {
21785 if(not defined $S2->{$K1}) {
21786 return 1;
21787 }
21788 }
21789 return 0;
21790}
21791
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021792sub defaultDumpPath($$)
21793{
21794 my ($N, $V) = @_;
21795 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21796}
21797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021798sub create_ABI_Dump()
21799{
21800 if(not -e $DumpAPI) {
21801 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21802 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021803
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021804 if(isDump($DumpAPI)) {
21805 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021806 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021807 else {
21808 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021809 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021810
21811 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021812 { # set to default: N
21813 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021814 }
21815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021816 initLogging(1);
21817 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021818
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021819 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021820 if($OutputDumpPath)
21821 { # user defined path
21822 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021823 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021824 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21825
21826 if(not $Archive and not $StdOut)
21827 { # check archive utilities
21828 if($OSgroup eq "windows")
21829 { # using zip
21830 my $ZipCmd = get_CmdPath("zip");
21831 if(not $ZipCmd) {
21832 exitStatus("Not_Found", "can't find \"zip\"");
21833 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021834 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021835 else
21836 { # using tar and gzip
21837 my $TarCmd = get_CmdPath("tar");
21838 if(not $TarCmd) {
21839 exitStatus("Not_Found", "can't find \"tar\"");
21840 }
21841 my $GzipCmd = get_CmdPath("gzip");
21842 if(not $GzipCmd) {
21843 exitStatus("Not_Found", "can't find \"gzip\"");
21844 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021845 }
21846 }
21847
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021848 if(not $Descriptor{1}{"Dump"})
21849 {
21850 if(not $CheckHeadersOnly) {
21851 readLibs(1);
21852 }
21853 if($CheckHeadersOnly) {
21854 setLanguage(1, "C++");
21855 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021856 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021857 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021858 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021859 if(not $Descriptor{1}{"Dump"})
21860 {
21861 if($Descriptor{1}{"Headers"}) {
21862 readHeaders(1);
21863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021864 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021865 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021866 if(not keys(%{$SymbolInfo{1}}))
21867 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021868 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021869 {
21870 if($CheckHeadersOnly) {
21871 exitStatus("Empty_Set", "the set of public symbols is empty");
21872 }
21873 else {
21874 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21875 }
21876 }
21877 }
21878 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021879 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021880 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21881 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021882 if($ExtraDump)
21883 { # add unmangled names to the ABI dump
21884 my @Names = ();
21885 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21886 {
21887 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21888 push(@Names, $MnglName);
21889 }
21890 }
21891 translateSymbols(@Names, 1);
21892 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21893 {
21894 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21895 {
21896 if(my $Unmangled = $tr_name{$MnglName})
21897 {
21898 if($MnglName ne $Unmangled) {
21899 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21900 }
21901 }
21902 }
21903 }
21904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021905
21906 my %GccConstants = (); # built-in GCC constants
21907 foreach my $Name (keys(%{$Constants{1}}))
21908 {
21909 if(not defined $Constants{1}{$Name}{"Header"})
21910 {
21911 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21912 delete($Constants{1}{$Name});
21913 }
21914 }
21915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021916 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021917 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021918 "TypeInfo" => $TypeInfo{1},
21919 "SymbolInfo" => $SymbolInfo{1},
21920 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021921 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021922 "SymbolVersion" => $SymVer{1},
21923 "LibraryVersion" => $Descriptor{1}{"Version"},
21924 "LibraryName" => $TargetLibraryName,
21925 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021926 "SkipTypes" => $SkipTypes{1},
21927 "SkipSymbols" => $SkipSymbols{1},
21928 "SkipNameSpaces" => $SkipNameSpaces{1},
21929 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021930 "Headers" => \%HeadersInfo,
21931 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021932 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021933 "NameSpaces" => $NestedNameSpaces{1},
21934 "Target" => $OStarget,
21935 "Arch" => getArch(1),
21936 "WordSize" => $WORD_SIZE{1},
21937 "GccVersion" => get_dumpversion($GCC_PATH),
21938 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21939 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21940 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021941 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021942 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021943 }
21944 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021945 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021947 if($ExtendedCheck)
21948 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021949 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021950 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021951 if($BinaryOnly)
21952 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021953 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021954 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021955 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021956 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021957 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021958 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21959 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021960 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021961
21962 my $ABI_DUMP = "";
21963 if($UseXML)
21964 {
21965 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021966 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021967 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021968 else
21969 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021970 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021972 if($StdOut)
21973 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021974 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021975 printMsg("INFO", "ABI dump has been generated to stdout");
21976 return;
21977 }
21978 else
21979 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021980 my ($DDir, $DName) = separate_path($DumpPath);
21981 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021982 if(not $Archive) {
21983 $DPath = $DumpPath;
21984 }
21985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021986 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021987
21988 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021989 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021990 close(DUMP);
21991
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021992 if(not -s $DPath) {
21993 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21994 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021995 if($Archive) {
21996 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021997 }
21998
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021999 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022000 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022001 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022002 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022003 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022004 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022005 # 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 +040022006 }
22007}
22008
22009sub quickEmptyReports()
22010{ # Quick "empty" reports
22011 # 4 times faster than merging equal dumps
22012 # NOTE: the dump contains the "LibraryVersion" attribute
22013 # if you change the version, then your dump will be different
22014 # OVERCOME: use -v1 and v2 options for comparing dumps
22015 # and don't change version in the XML descriptor (and dumps)
22016 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22017 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22018 {
22019 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
22020 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
22021 if($FilePath1 and $FilePath2)
22022 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022023 my $Line = readLineNum($FilePath1, 0);
22024 if($Line=~/xml/)
22025 { # XML format
22026 # is not supported yet
22027 return;
22028 }
22029
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022030 local $/ = undef;
22031
22032 open(DUMP1, $FilePath1);
22033 my $Content1 = <DUMP1>;
22034 close(DUMP1);
22035
22036 open(DUMP2, $FilePath2);
22037 my $Content2 = <DUMP2>;
22038 close(DUMP2);
22039
22040 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022041 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022042 # clean memory
22043 undef $Content2;
22044
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022045 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022046 my $ABIdump = eval($Content1);
22047
22048 # clean memory
22049 undef $Content1;
22050
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022051 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022052 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 +040022053 }
22054 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022055 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022056 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22057 }
22058 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022059 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022060 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22061 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022062 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022063 read_Libs_DumpInfo($ABIdump, 1);
22064 read_Machine_DumpInfo($ABIdump, 1);
22065 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022066
22067 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22068 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22069
22070 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
22071 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
22072
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022073 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22074 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22075 exitReport();
22076 }
22077 }
22078 }
22079}
22080
22081sub initLogging($)
22082{
22083 my $LibVersion = $_[0];
22084 # create log directory
22085 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22086 if($OutputLogPath{$LibVersion})
22087 { # user-defined by -log-path option
22088 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22089 }
22090 if($LogMode ne "n") {
22091 mkpath($LOG_DIR);
22092 }
22093 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022094 if($Debug)
22095 { # debug directory
22096 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022097
22098 if(not $ExtraInfo)
22099 { # enable --extra-info
22100 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022102 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022103 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022104}
22105
22106sub writeLog($$)
22107{
22108 my ($LibVersion, $Msg) = @_;
22109 if($LogMode ne "n") {
22110 appendFile($LOG_PATH{$LibVersion}, $Msg);
22111 }
22112}
22113
22114sub resetLogging($)
22115{
22116 my $LibVersion = $_[0];
22117 if($LogMode!~/a|n/)
22118 { # remove old log
22119 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022120 if($Debug) {
22121 rmtree($DEBUG_PATH{$LibVersion});
22122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022123 }
22124}
22125
22126sub printErrorLog($)
22127{
22128 my $LibVersion = $_[0];
22129 if($LogMode ne "n") {
22130 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22131 }
22132}
22133
22134sub isDump($)
22135{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022136 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22137 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022138 return $1;
22139 }
22140 return 0;
22141}
22142
22143sub isDump_U($)
22144{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022145 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022146 return $1;
22147 }
22148 return 0;
22149}
22150
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022151sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022152{
22153 # read input XML descriptors or ABI dumps
22154 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022155 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022156 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022157 if(not -e $Descriptor{1}{"Path"}) {
22158 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022159 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022160
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022161 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022162 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022163 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022164 if(not -e $Descriptor{2}{"Path"}) {
22165 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022166 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022168 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022169 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022170 and isDump($Descriptor{2}{"Path"}))
22171 { # optimization: equal ABI dumps
22172 quickEmptyReports();
22173 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022174
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022175 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022176
22177 if(isDump($Descriptor{1}{"Path"})) {
22178 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022179 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022180 else {
22181 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22182 }
22183
22184 if(isDump($Descriptor{2}{"Path"})) {
22185 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22186 }
22187 else {
22188 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022189 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022190
22191 if(not $Descriptor{1}{"Version"})
22192 { # set to default: X
22193 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022194 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022195 }
22196
22197 if(not $Descriptor{2}{"Version"})
22198 { # set to default: Y
22199 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022200 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022201 }
22202
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022203 if(not $UsedDump{1}{"V"}) {
22204 initLogging(1);
22205 }
22206
22207 if(not $UsedDump{2}{"V"}) {
22208 initLogging(2);
22209 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022210
22211 # check input data
22212 if(not $Descriptor{1}{"Headers"}) {
22213 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022214 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022215 if(not $Descriptor{2}{"Headers"}) {
22216 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022217 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022218
22219 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022220 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022221 if(not $Descriptor{1}{"Libs"}) {
22222 exitStatus("Error", "can't find libraries info in descriptor d1");
22223 }
22224 if(not $Descriptor{2}{"Libs"}) {
22225 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022226 }
22227 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022228
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022229 if($UseDumps)
22230 { # --use-dumps
22231 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022232 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22233 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022234
22235 unlink($DumpPath1);
22236 unlink($DumpPath2);
22237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022238 my $pid = fork();
22239 if($pid)
22240 { # dump on two CPU cores
22241 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22242 if($RelativeDirectory{1}) {
22243 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22244 }
22245 if($OutputLogPath{1}) {
22246 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22247 }
22248 if($CrossGcc) {
22249 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22250 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022251 if($Quiet)
22252 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022253 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022254 @PARAMS = (@PARAMS, "-logging-mode", "a");
22255 }
22256 elsif($LogMode and $LogMode ne "w")
22257 { # "w" is default
22258 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022259 }
22260 if($ExtendedCheck) {
22261 @PARAMS = (@PARAMS, "-extended");
22262 }
22263 if($UserLang) {
22264 @PARAMS = (@PARAMS, "-lang", $UserLang);
22265 }
22266 if($TargetVersion{1}) {
22267 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22268 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022269 if($BinaryOnly) {
22270 @PARAMS = (@PARAMS, "-binary");
22271 }
22272 if($SourceOnly) {
22273 @PARAMS = (@PARAMS, "-source");
22274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022275 if($SortDump) {
22276 @PARAMS = (@PARAMS, "-sort");
22277 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022278 if($DumpFormat and $DumpFormat ne "perl") {
22279 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22280 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022281 if($CheckHeadersOnly) {
22282 @PARAMS = (@PARAMS, "-headers-only");
22283 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022284 if($Debug)
22285 {
22286 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022287 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022289 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022290 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022291 exit(1);
22292 }
22293 }
22294 else
22295 { # child
22296 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22297 if($RelativeDirectory{2}) {
22298 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22299 }
22300 if($OutputLogPath{2}) {
22301 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22302 }
22303 if($CrossGcc) {
22304 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22305 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022306 if($Quiet)
22307 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022308 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022309 @PARAMS = (@PARAMS, "-logging-mode", "a");
22310 }
22311 elsif($LogMode and $LogMode ne "w")
22312 { # "w" is default
22313 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022314 }
22315 if($ExtendedCheck) {
22316 @PARAMS = (@PARAMS, "-extended");
22317 }
22318 if($UserLang) {
22319 @PARAMS = (@PARAMS, "-lang", $UserLang);
22320 }
22321 if($TargetVersion{2}) {
22322 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22323 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022324 if($BinaryOnly) {
22325 @PARAMS = (@PARAMS, "-binary");
22326 }
22327 if($SourceOnly) {
22328 @PARAMS = (@PARAMS, "-source");
22329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022330 if($SortDump) {
22331 @PARAMS = (@PARAMS, "-sort");
22332 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022333 if($DumpFormat and $DumpFormat ne "perl") {
22334 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22335 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022336 if($CheckHeadersOnly) {
22337 @PARAMS = (@PARAMS, "-headers-only");
22338 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022339 if($Debug)
22340 {
22341 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022342 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022344 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022345 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022346 exit(1);
22347 }
22348 else {
22349 exit(0);
22350 }
22351 }
22352 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022354 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022355 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22356 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022357 if($TargetTitle ne $TargetLibraryName) {
22358 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022359 }
22360 if($ShowRetVal) {
22361 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22362 }
22363 if($CrossGcc) {
22364 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22365 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022366 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22367 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022368 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022369 }
22370 if($ReportFormat and $ReportFormat ne "html")
22371 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022372 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22373 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022374 if($OutputReportPath) {
22375 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22376 }
22377 if($BinaryReportPath) {
22378 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22379 }
22380 if($SourceReportPath) {
22381 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22382 }
22383 if($LoggingPath) {
22384 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22385 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022386 if($CheckHeadersOnly) {
22387 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22388 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022389 if($BinaryOnly) {
22390 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22391 }
22392 if($SourceOnly) {
22393 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22394 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022395 if($Debug)
22396 {
22397 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22398 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022400 system("perl", $0, @CMP_PARAMS);
22401 exit($?>>8);
22402 }
22403 if(not $Descriptor{1}{"Dump"}
22404 or not $Descriptor{2}{"Dump"})
22405 { # need GCC toolchain to analyze
22406 # header files and libraries
22407 detect_default_paths("inc|lib|gcc");
22408 }
22409 if(not $Descriptor{1}{"Dump"})
22410 {
22411 if(not $CheckHeadersOnly) {
22412 readLibs(1);
22413 }
22414 if($CheckHeadersOnly) {
22415 setLanguage(1, "C++");
22416 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022417 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022418 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022419 }
22420 if(not $Descriptor{2}{"Dump"})
22421 {
22422 if(not $CheckHeadersOnly) {
22423 readLibs(2);
22424 }
22425 if($CheckHeadersOnly) {
22426 setLanguage(2, "C++");
22427 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022428 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022429 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022430 }
22431 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22432 { # support for old ABI dumps
22433 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022434 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022435 {
22436 $WORD_SIZE{1} = $WORD_SIZE{2};
22437 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22438 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022439 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022440 {
22441 $WORD_SIZE{2} = $WORD_SIZE{1};
22442 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22443 }
22444 }
22445 elsif(not $WORD_SIZE{1}
22446 and not $WORD_SIZE{2})
22447 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022448 $WORD_SIZE{1} = "4";
22449 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022450 }
22451 if($Descriptor{1}{"Dump"})
22452 { # support for old ABI dumps
22453 prepareTypes(1);
22454 }
22455 if($Descriptor{2}{"Dump"})
22456 { # support for old ABI dumps
22457 prepareTypes(2);
22458 }
22459 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22460 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22461 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022462 # process input data
22463 if($Descriptor{1}{"Headers"}
22464 and not $Descriptor{1}{"Dump"}) {
22465 readHeaders(1);
22466 }
22467 if($Descriptor{2}{"Headers"}
22468 and not $Descriptor{2}{"Dump"}) {
22469 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022471
22472 # clean memory
22473 %SystemHeaders = ();
22474 %mangled_name_gcc = ();
22475
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022476 prepareSymbols(1);
22477 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022478
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022479 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022480 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022481
22482 # Virtual Tables
22483 registerVTable(1);
22484 registerVTable(2);
22485
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022486 if(not checkDump(1, "1.22")
22487 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022488 { # support for old ABI dumps
22489 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22490 {
22491 if($ClassName=~/</)
22492 { # templates
22493 if(not defined $VirtualTable{1}{$ClassName})
22494 { # synchronize
22495 delete($VirtualTable{2}{$ClassName});
22496 }
22497 }
22498 }
22499 }
22500
22501 registerOverriding(1);
22502 registerOverriding(2);
22503
22504 setVirtFuncPositions(1);
22505 setVirtFuncPositions(2);
22506
22507 # Other
22508 addParamNames(1);
22509 addParamNames(2);
22510
22511 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022512}
22513
22514sub compareAPIs($)
22515{
22516 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022517
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022518 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022519 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022520
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022521 if($Level eq "Binary") {
22522 printMsg("INFO", "comparing ABIs ...");
22523 }
22524 else {
22525 printMsg("INFO", "comparing APIs ...");
22526 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022527
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022528 if($CheckHeadersOnly
22529 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022530 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022531 detectAdded_H($Level);
22532 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022533 }
22534 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022535 { # added/removed in libs
22536 detectAdded($Level);
22537 detectRemoved($Level);
22538 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022539
22540 mergeSymbols($Level);
22541 if(keys(%{$CheckedSymbols{$Level}})) {
22542 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022543 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022544
22545 $Cache{"mergeTypes"} = (); # free memory
22546
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022547 if($CheckHeadersOnly
22548 or $Level eq "Source")
22549 { # added/removed in headers
22550 mergeHeaders($Level);
22551 }
22552 else
22553 { # added/removed in libs
22554 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022555 }
22556}
22557
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022558sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559{
22560 my %Opts = (
22561 "OStarget"=>$OStarget,
22562 "Debug"=>$Debug,
22563 "Quiet"=>$Quiet,
22564 "LogMode"=>$LogMode,
22565 "CheckHeadersOnly"=>$CheckHeadersOnly,
22566
22567 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022568 "GCC_PATH"=>$GCC_PATH,
22569 "TargetSysInfo"=>$TargetSysInfo,
22570 "CrossPrefix"=>$CrossPrefix,
22571 "TargetLibraryName"=>$TargetLibraryName,
22572 "CrossGcc"=>$CrossGcc,
22573 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022574 "NoStdInc"=>$NoStdInc,
22575
22576 "BinaryOnly" => $BinaryOnly,
22577 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022578 );
22579 return \%Opts;
22580}
22581
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022582sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022583{
22584 my %CODE_ERROR = reverse(%ERROR_CODE);
22585 return $CODE_ERROR{$_[0]};
22586}
22587
22588sub scenario()
22589{
22590 if($StdOut)
22591 { # enable quiet mode
22592 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022593 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022594 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022595 if(not $LogMode)
22596 { # default
22597 $LogMode = "w";
22598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022599 if($UserLang)
22600 { # --lang=C++
22601 $UserLang = uc($UserLang);
22602 $COMMON_LANGUAGE{1}=$UserLang;
22603 $COMMON_LANGUAGE{2}=$UserLang;
22604 }
22605 if($LoggingPath)
22606 {
22607 $OutputLogPath{1} = $LoggingPath;
22608 $OutputLogPath{2} = $LoggingPath;
22609 if($Quiet) {
22610 $COMMON_LOG_PATH = $LoggingPath;
22611 }
22612 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022613
22614 if($SkipInternalSymbols) {
22615 $SkipInternalSymbols=~s/\*/.*/g;
22616 }
22617
22618 if($SkipInternalTypes) {
22619 $SkipInternalTypes=~s/\*/.*/g;
22620 }
22621
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022622 if($Quick) {
22623 $ADD_TMPL_INSTANCES = 0;
22624 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022625 if($OutputDumpPath)
22626 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022627 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022628 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22629 }
22630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022631 if($BinaryOnly and $SourceOnly)
22632 { # both --binary and --source
22633 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022634 if(not $CmpSystems)
22635 {
22636 $BinaryOnly = 0;
22637 $SourceOnly = 0;
22638 }
22639
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022640 $DoubleReport = 1;
22641 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022642
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022643 if($OutputReportPath)
22644 { # --report-path
22645 $DoubleReport = 0;
22646 $JoinReport = 1;
22647 }
22648 }
22649 elsif($BinaryOnly or $SourceOnly)
22650 { # --binary or --source
22651 $DoubleReport = 0;
22652 $JoinReport = 0;
22653 }
22654 if($UseXML)
22655 { # --xml option
22656 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022657 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022659 if($ReportFormat)
22660 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022661 $ReportFormat = lc($ReportFormat);
22662 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022663 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022664 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022665 if($ReportFormat eq "htm")
22666 { # HTM == HTML
22667 $ReportFormat = "html";
22668 }
22669 elsif($ReportFormat eq "xml")
22670 { # --report-format=XML equal to --xml
22671 $UseXML = 1;
22672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022673 }
22674 else
22675 { # default: HTML
22676 $ReportFormat = "html";
22677 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022678 if($DumpFormat)
22679 { # validate
22680 $DumpFormat = lc($DumpFormat);
22681 if($DumpFormat!~/\A(xml|perl)\Z/) {
22682 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22683 }
22684 if($DumpFormat eq "xml")
22685 { # --dump-format=XML equal to --xml
22686 $UseXML = 1;
22687 }
22688 }
22689 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022690 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022691 $DumpFormat = "perl";
22692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022693 if($Quiet and $LogMode!~/a|n/)
22694 { # --quiet log
22695 if(-f $COMMON_LOG_PATH) {
22696 unlink($COMMON_LOG_PATH);
22697 }
22698 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022699 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022700 $CheckUndefined = 1;
22701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022702 if($TestTool and $UseDumps)
22703 { # --test && --use-dumps == --test-dump
22704 $TestDump = 1;
22705 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022706 if($Tolerant)
22707 { # enable all
22708 $Tolerance = 1234;
22709 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022710 if($Help)
22711 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022712 HELP_MESSAGE();
22713 exit(0);
22714 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022715 if($InfoMsg)
22716 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022717 INFO_MESSAGE();
22718 exit(0);
22719 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022720 if($ShowVersion)
22721 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022722 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 +040022723 exit(0);
22724 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022725 if($DumpVersion)
22726 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022727 printMsg("INFO", $TOOL_VERSION);
22728 exit(0);
22729 }
22730 if($ExtendedCheck) {
22731 $CheckHeadersOnly = 1;
22732 }
22733 if($SystemRoot_Opt)
22734 { # user defined root
22735 if(not -e $SystemRoot_Opt) {
22736 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22737 }
22738 $SystemRoot = $SystemRoot_Opt;
22739 $SystemRoot=~s/[\/]+\Z//g;
22740 if($SystemRoot) {
22741 $SystemRoot = get_abs_path($SystemRoot);
22742 }
22743 }
22744 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022745
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022746 if($SortDump)
22747 {
22748 $Data::Dumper::Useperl = 1;
22749 $Data::Dumper::Sortkeys = \&dump_sorting;
22750 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022751
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022752 if($TargetLibsPath)
22753 {
22754 if(not -f $TargetLibsPath) {
22755 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22756 }
22757 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22758 $TargetLibs{$Lib} = 1;
22759 }
22760 }
22761 if($TargetHeadersPath)
22762 { # --headers-list
22763 if(not -f $TargetHeadersPath) {
22764 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22765 }
22766 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22767 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022768 $TargetHeaders{1}{get_filename($Header)} = 1;
22769 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022770 }
22771 }
22772 if($TargetHeader)
22773 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022774 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22775 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022776 }
22777 if($TestTool
22778 or $TestDump)
22779 { # --test, --test-dump
22780 detect_default_paths("bin|gcc"); # to compile libs
22781 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022782 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022783 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022784 exit(0);
22785 }
22786 if($DumpSystem)
22787 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022788
22789 if(not $TargetSysInfo) {
22790 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22791 }
22792
22793 if(not -d $TargetSysInfo) {
22794 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22795 }
22796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022797 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022798 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022799 { # system XML descriptor
22800 if(not -f $DumpSystem) {
22801 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22802 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022803
22804 my $SDesc = readFile($DumpSystem);
22805 if(my $RelDir = $RelativeDirectory{1}) {
22806 $SDesc =~ s/{RELPATH}/$RelDir/g;
22807 }
22808
22809 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022810 foreach (@{$Ret->{"Tools"}})
22811 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022812 push_U($SystemPaths{"bin"}, $_);
22813 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022814 }
22815 if($Ret->{"CrossPrefix"}) {
22816 $CrossPrefix = $Ret->{"CrossPrefix"};
22817 }
22818 }
22819 elsif($SystemRoot_Opt)
22820 { # -sysroot "/" option
22821 # default target: /usr/lib, /usr/include
22822 # search libs: /usr/lib and /lib
22823 if(not -e $SystemRoot."/usr/lib") {
22824 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22825 }
22826 if(not -e $SystemRoot."/lib") {
22827 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22828 }
22829 if(not -e $SystemRoot."/usr/include") {
22830 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22831 }
22832 readSystemDescriptor("
22833 <name>
22834 $DumpSystem
22835 </name>
22836 <headers>
22837 $SystemRoot/usr/include
22838 </headers>
22839 <libs>
22840 $SystemRoot/usr/lib
22841 </libs>
22842 <search_libs>
22843 $SystemRoot/lib
22844 </search_libs>");
22845 }
22846 else {
22847 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22848 }
22849 detect_default_paths("bin|gcc"); # to check symbols
22850 if($OStarget eq "windows")
22851 { # to run dumpbin.exe
22852 # and undname.exe
22853 check_win32_env();
22854 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022855 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022856 exit(0);
22857 }
22858 if($CmpSystems)
22859 { # --cmp-systems
22860 detect_default_paths("bin"); # to extract dumps
22861 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022862 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022863 exit(0);
22864 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022865 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022866 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022867 }
22868 else
22869 { # validate library name
22870 if($TargetLibraryName=~/[\*\/\\]/) {
22871 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22872 }
22873 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022874 if(not $TargetTitle) {
22875 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022876 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022877
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022878 if($SymbolsListPath)
22879 {
22880 if(not -f $SymbolsListPath) {
22881 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22882 }
22883 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22884 $SymbolsList{$Interface} = 1;
22885 }
22886 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022887 if($TypesListPath)
22888 {
22889 if(not -f $TypesListPath) {
22890 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22891 }
22892 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22893 $TypesList{$Type} = 1;
22894 }
22895 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022896 if($SkipSymbolsListPath)
22897 {
22898 if(not -f $SkipSymbolsListPath) {
22899 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22900 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022901 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22902 {
22903 $SkipSymbols{1}{$Interface} = 1;
22904 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022905 }
22906 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030022907 if($SkipTypesListPath)
22908 {
22909 if(not -f $SkipTypesListPath) {
22910 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
22911 }
22912 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
22913 {
22914 $SkipTypes{1}{$Type} = 1;
22915 $SkipTypes{2}{$Type} = 1;
22916 }
22917 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022918 if($SkipHeadersPath)
22919 {
22920 if(not -f $SkipHeadersPath) {
22921 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22922 }
22923 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022924 { # register for both versions
22925 $SkipHeadersList{1}{$Path} = 1;
22926 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022927 my ($CPath, $Type) = classifyPath($Path);
22928 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022929 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022930 }
22931 }
22932 if($ParamNamesPath)
22933 {
22934 if(not -f $ParamNamesPath) {
22935 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22936 }
22937 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22938 {
22939 if($Line=~s/\A(\w+)\;//)
22940 {
22941 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022942 if($Line=~/;(\d+);/)
22943 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022944 while($Line=~s/(\d+);(\w+)//) {
22945 $AddIntParams{$Interface}{$1}=$2;
22946 }
22947 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022948 else
22949 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022950 my $Num = 0;
22951 foreach my $Name (split(/;/, $Line)) {
22952 $AddIntParams{$Interface}{$Num++}=$Name;
22953 }
22954 }
22955 }
22956 }
22957 }
22958 if($AppPath)
22959 {
22960 if(not -f $AppPath) {
22961 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22962 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022963
22964 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022965 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022966 $SymbolsList_App{$Interface} = 1;
22967 }
22968 }
22969 if($DumpAPI)
22970 { # --dump-abi
22971 # make an API dump
22972 create_ABI_Dump();
22973 exit($COMPILE_ERRORS);
22974 }
22975 # default: compare APIs
22976 # -d1 <path>
22977 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022978 compareInit();
22979 if($JoinReport or $DoubleReport)
22980 {
22981 compareAPIs("Binary");
22982 compareAPIs("Source");
22983 }
22984 elsif($BinaryOnly) {
22985 compareAPIs("Binary");
22986 }
22987 elsif($SourceOnly) {
22988 compareAPIs("Source");
22989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022990 exitReport();
22991}
22992
22993scenario();