blob: 4ea32b983599cb74c7d4dc061af6c7b38700ba54 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03003# ABI Compliance Checker (ABICC) 1.99.20
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 Ponomarenkob3118d92016-05-14 17:55:06 +030063my $TOOL_VERSION = "1.99.20";
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.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400546
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400547 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400548 Compare two system ABI dumps. Create compatibility reports for each
549 library and the common HTML report including the summary of test
550 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400551 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400552
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400553 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400554 The file with a list of libraries, that should be dumped by
555 the -dump-system option or should be checked by the -cmp-systems option.
556
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400557 -ext|-extended
558 If your library A is supposed to be used by other library B and you
559 want to control the ABI of B, then you should enable this option. The
560 tool will check for changes in all data types, even if they are not
561 used by any function in the library A. Such data types are not part
562 of the A library ABI, but may be a part of the ABI of the B library.
563
564 The short scheme is:
565 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
566
567 -q|-quiet
568 Print all messages to the file instead of stdout and stderr.
569 Default path (can be changed by -log-path option):
570 $COMMON_LOG_PATH
571
572 -stdout
573 Print analysis results (compatibility reports and ABI dumps) to stdout
574 instead of creating a file. This would allow piping data to other programs.
575
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400576 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400577 Change format of compatibility report.
578 Formats:
579 htm - HTML format (default)
580 xml - XML format
581
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400582 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400583 Change format of ABI dump.
584 Formats:
585 perl - Data::Dumper format (default)
586 xml - XML format
587
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400588 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400589 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400590
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400591 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400592 Set library language (C or C++). You can use this option if the tool
593 cannot auto-detect a language. This option may be useful for checking
594 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400595
596 -arch ARCH
597 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
598 ect.). The option is useful if the tool cannot detect correct architecture
599 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400600
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400601 -binary|-bin|-abi
602 Show \"Binary\" compatibility problems only.
603 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400604 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400605
606 -source|-src|-api
607 Show \"Source\" compatibility problems only.
608 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400609 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400610
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400611 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400612 The maximum number of affected symbols listed under the description
613 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400615OTHER OPTIONS:
616 -test
617 Run internal tests. Create two binary incompatible versions of a sample
618 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300619 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400620
621 -test-dump
622 Test ability to create, read and compare ABI dumps.
623
624 -debug
625 Debugging mode. Print debug info on the screen. Save intermediate
626 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400627 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400628
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400629 Also consider using --dump option for debugging the tool.
630
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400631 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400632 If your header files are written in C language and can be compiled
633 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
634 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400635
636 -cpp-incompatible
637 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400638
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400639 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400640 Path to file with the function parameter names. It can be used
641 for improving report view if the library header files have no
642 parameter names. File format:
643
644 func1;param1;param2;param3 ...
645 func2;param1;param2;param3 ...
646 ...
647
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400648 -relpath PATH
649 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400650 for dumping the library ABI (see -dump option).
651
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400652 -relpath1 PATH
653 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400654
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400655 -relpath2 PATH
656 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400657
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400658 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400659 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400660 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400661 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400663 -sort
664 Enable sorting of data in ABI dumps.
665
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400666 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400667 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400668 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400669 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400670
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400672 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400675
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400676 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400677 Path to \"Source\" compatibility report.
678 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400679 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400682 Log path for all messages.
683 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400684 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400685
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400686 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400687 Log path for 1st version of a library.
688 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400690
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692 Log path for 2nd version of a library.
693 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697 Change logging mode.
698 Modes:
699 w - overwrite old logs (default)
700 a - append old logs
701 n - do not write any logs
702
703 -list-affected
704 Generate file with the list of incompatible
705 symbols beside the HTML compatibility report.
706 Use 'c++filt \@file' command from GNU binutils
707 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400708 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400710 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400712 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400713 The component name in the title and summary of the HTML report.
714 Default:
715 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300716
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300717 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400719 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720
721 -extra-info DIR
722 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400723
724 -extra-dump
725 Create extended ABI dump containing all symbols
726 from the translation unit.
727
728 -force
729 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400730
731 -tolerance LEVEL
732 Apply a set of heuristics to successfully compile input
733 header files. You can enable several tolerance levels by
734 joining them into one string (e.g. 13, 124, etc.).
735 Levels:
736 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
737 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
738 3 - skip headers that iclude non-Linux headers
739 4 - skip headers included by others
740
741 -tolerant
742 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400743
744 -check
745 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400746
747 -quick
748 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400749
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300750 -skip-internal-symbols PATTERN
751 Do not check symbols matched by the pattern.
752
753 -skip-internal-types PATTERN
754 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300755
756 -check-private-abi
757 Check data types from the private part of the ABI when
758 comparing ABI dumps created by the ABI Dumper tool with
759 use of the -public-headers option.
760
761 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400762
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400763REPORT:
764 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400765 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400766
767 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400768 logs/LIB_NAME/V1/log.txt
769 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400770
771EXIT CODES:
772 0 - Compatible. The tool has run without any errors.
773 non-zero - Incompatible or the tool has run with errors.
774
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400775MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300776 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400777}
778
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400779my %Operator_Indication = (
780 "not" => "~",
781 "assign" => "=",
782 "andassign" => "&=",
783 "orassign" => "|=",
784 "xorassign" => "^=",
785 "or" => "|",
786 "xor" => "^",
787 "addr" => "&",
788 "and" => "&",
789 "lnot" => "!",
790 "eq" => "==",
791 "ne" => "!=",
792 "lt" => "<",
793 "lshift" => "<<",
794 "lshiftassign" => "<<=",
795 "rshiftassign" => ">>=",
796 "call" => "()",
797 "mod" => "%",
798 "modassign" => "%=",
799 "subs" => "[]",
800 "land" => "&&",
801 "lor" => "||",
802 "rshift" => ">>",
803 "ref" => "->",
804 "le" => "<=",
805 "deref" => "*",
806 "mult" => "*",
807 "preinc" => "++",
808 "delete" => " delete",
809 "vecnew" => " new[]",
810 "vecdelete" => " delete[]",
811 "predec" => "--",
812 "postinc" => "++",
813 "postdec" => "--",
814 "plusassign" => "+=",
815 "plus" => "+",
816 "minus" => "-",
817 "minusassign" => "-=",
818 "gt" => ">",
819 "ge" => ">=",
820 "new" => " new",
821 "multassign" => "*=",
822 "divassign" => "/=",
823 "div" => "/",
824 "neg" => "-",
825 "pos" => "+",
826 "memref" => "->*",
827 "compound" => "," );
828
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400829my %UnknownOperator;
830
831my %NodeType= (
832 "array_type" => "Array",
833 "binfo" => "Other",
834 "boolean_type" => "Intrinsic",
835 "complex_type" => "Intrinsic",
836 "const_decl" => "Other",
837 "enumeral_type" => "Enum",
838 "field_decl" => "Other",
839 "function_decl" => "Other",
840 "function_type" => "FunctionType",
841 "identifier_node" => "Other",
842 "integer_cst" => "Other",
843 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400844 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400845 "method_type" => "MethodType",
846 "namespace_decl" => "Other",
847 "parm_decl" => "Other",
848 "pointer_type" => "Pointer",
849 "real_cst" => "Other",
850 "real_type" => "Intrinsic",
851 "record_type" => "Struct",
852 "reference_type" => "Ref",
853 "string_cst" => "Other",
854 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400855 "template_type_parm" => "TemplateParam",
856 "typename_type" => "TypeName",
857 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400858 "tree_list" => "Other",
859 "tree_vec" => "Other",
860 "type_decl" => "Other",
861 "union_type" => "Union",
862 "var_decl" => "Other",
863 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400864 "nop_expr" => "Other", #
865 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400866 "offset_type" => "Other" );
867
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400868my %CppKeywords_C = map {$_=>1} (
869 # C++ 2003 keywords
870 "public",
871 "protected",
872 "private",
873 "default",
874 "template",
875 "new",
876 #"asm",
877 "dynamic_cast",
878 "auto",
879 "try",
880 "namespace",
881 "typename",
882 "using",
883 "reinterpret_cast",
884 "friend",
885 "class",
886 "virtual",
887 "const_cast",
888 "mutable",
889 "static_cast",
890 "export",
891 # C++0x keywords
892 "noexcept",
893 "nullptr",
894 "constexpr",
895 "static_assert",
896 "explicit",
897 # cannot be used as a macro name
898 # as it is an operator in C++
899 "and",
900 #"and_eq",
901 "not",
902 #"not_eq",
903 "or"
904 #"or_eq",
905 #"bitand",
906 #"bitor",
907 #"xor",
908 #"xor_eq",
909 #"compl"
910);
911
912my %CppKeywords_F = map {$_=>1} (
913 "delete",
914 "catch",
915 "alignof",
916 "thread_local",
917 "decltype",
918 "typeid"
919);
920
921my %CppKeywords_O = map {$_=>1} (
922 "bool",
923 "register",
924 "inline",
925 "operator"
926);
927
928my %CppKeywords_A = map {$_=>1} (
929 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400930 "throw",
931 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400932);
933
934foreach (keys(%CppKeywords_C),
935keys(%CppKeywords_F),
936keys(%CppKeywords_O)) {
937 $CppKeywords_A{$_}=1;
938}
939
940# Header file extensions as described by gcc
941my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
942
943my %IntrinsicMangling = (
944 "void" => "v",
945 "bool" => "b",
946 "wchar_t" => "w",
947 "char" => "c",
948 "signed char" => "a",
949 "unsigned char" => "h",
950 "short" => "s",
951 "unsigned short" => "t",
952 "int" => "i",
953 "unsigned int" => "j",
954 "long" => "l",
955 "unsigned long" => "m",
956 "long long" => "x",
957 "__int64" => "x",
958 "unsigned long long" => "y",
959 "__int128" => "n",
960 "unsigned __int128" => "o",
961 "float" => "f",
962 "double" => "d",
963 "long double" => "e",
964 "__float80" => "e",
965 "__float128" => "g",
966 "..." => "z"
967);
968
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400969my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
970
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400971my %StdcxxMangling = (
972 "3std"=>"St",
973 "3std9allocator"=>"Sa",
974 "3std12basic_string"=>"Sb",
975 "3std12basic_stringIcE"=>"Ss",
976 "3std13basic_istreamIcE"=>"Si",
977 "3std13basic_ostreamIcE"=>"So",
978 "3std14basic_iostreamIcE"=>"Sd"
979);
980
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400981my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400982my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
983
984my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400985my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400987my %ConstantSuffix = (
988 "unsigned int"=>"u",
989 "long"=>"l",
990 "unsigned long"=>"ul",
991 "long long"=>"ll",
992 "unsigned long long"=>"ull"
993);
994
995my %ConstantSuffixR =
996reverse(%ConstantSuffix);
997
998my %OperatorMangling = (
999 "~" => "co",
1000 "=" => "aS",
1001 "|" => "or",
1002 "^" => "eo",
1003 "&" => "an",#ad (addr)
1004 "==" => "eq",
1005 "!" => "nt",
1006 "!=" => "ne",
1007 "<" => "lt",
1008 "<=" => "le",
1009 "<<" => "ls",
1010 "<<=" => "lS",
1011 ">" => "gt",
1012 ">=" => "ge",
1013 ">>" => "rs",
1014 ">>=" => "rS",
1015 "()" => "cl",
1016 "%" => "rm",
1017 "[]" => "ix",
1018 "&&" => "aa",
1019 "||" => "oo",
1020 "*" => "ml",#de (deref)
1021 "++" => "pp",#
1022 "--" => "mm",#
1023 "new" => "nw",
1024 "delete" => "dl",
1025 "new[]" => "na",
1026 "delete[]" => "da",
1027 "+=" => "pL",
1028 "+" => "pl",#ps (pos)
1029 "-" => "mi",#ng (neg)
1030 "-=" => "mI",
1031 "*=" => "mL",
1032 "/=" => "dV",
1033 "&=" => "aN",
1034 "|=" => "oR",
1035 "%=" => "rM",
1036 "^=" => "eO",
1037 "/" => "dv",
1038 "->*" => "pm",
1039 "->" => "pt",#rf (ref)
1040 "," => "cm",
1041 "?" => "qu",
1042 "." => "dt",
1043 "sizeof"=> "sz"#st
1044);
1045
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001046my %Intrinsic_Keywords = map {$_=>1} (
1047 "true",
1048 "false",
1049 "_Bool",
1050 "_Complex",
1051 "const",
1052 "int",
1053 "long",
1054 "void",
1055 "short",
1056 "float",
1057 "volatile",
1058 "restrict",
1059 "unsigned",
1060 "signed",
1061 "char",
1062 "double",
1063 "class",
1064 "struct",
1065 "union",
1066 "enum"
1067);
1068
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001069my %GlibcHeader = map {$_=>1} (
1070 "aliases.h",
1071 "argp.h",
1072 "argz.h",
1073 "assert.h",
1074 "cpio.h",
1075 "ctype.h",
1076 "dirent.h",
1077 "envz.h",
1078 "errno.h",
1079 "error.h",
1080 "execinfo.h",
1081 "fcntl.h",
1082 "fstab.h",
1083 "ftw.h",
1084 "glob.h",
1085 "grp.h",
1086 "iconv.h",
1087 "ifaddrs.h",
1088 "inttypes.h",
1089 "langinfo.h",
1090 "limits.h",
1091 "link.h",
1092 "locale.h",
1093 "malloc.h",
1094 "math.h",
1095 "mntent.h",
1096 "monetary.h",
1097 "nl_types.h",
1098 "obstack.h",
1099 "printf.h",
1100 "pwd.h",
1101 "regex.h",
1102 "sched.h",
1103 "search.h",
1104 "setjmp.h",
1105 "shadow.h",
1106 "signal.h",
1107 "spawn.h",
1108 "stdarg.h",
1109 "stdint.h",
1110 "stdio.h",
1111 "stdlib.h",
1112 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001113 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001114 "tar.h",
1115 "termios.h",
1116 "time.h",
1117 "ulimit.h",
1118 "unistd.h",
1119 "utime.h",
1120 "wchar.h",
1121 "wctype.h",
1122 "wordexp.h" );
1123
1124my %GlibcDir = map {$_=>1} (
1125 "arpa",
1126 "bits",
1127 "gnu",
1128 "netinet",
1129 "net",
1130 "nfs",
1131 "rpc",
1132 "sys",
1133 "linux" );
1134
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001135my %WinHeaders = map {$_=>1} (
1136 "dos.h",
1137 "process.h",
1138 "winsock.h",
1139 "config-win.h",
1140 "mem.h",
1141 "windows.h",
1142 "winsock2.h",
1143 "crtdbg.h",
1144 "ws2tcpip.h"
1145);
1146
1147my %ObsoleteHeaders = map {$_=>1} (
1148 "iostream.h",
1149 "fstream.h"
1150);
1151
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001152my %AlienHeaders = map {$_=>1} (
1153 # Solaris
1154 "thread.h",
1155 "sys/atomic.h",
1156 # HPUX
1157 "sys/stream.h",
1158 # Symbian
1159 "AknDoc.h",
1160 # Atari ST
1161 "ext.h",
1162 "tos.h",
1163 # MS-DOS
1164 "alloc.h",
1165 # Sparc
1166 "sys/atomic.h"
1167);
1168
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001169my %ConfHeaders = map {$_=>1} (
1170 "atomic",
1171 "conf.h",
1172 "config.h",
1173 "configure.h",
1174 "build.h",
1175 "setup.h"
1176);
1177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001178my %LocalIncludes = map {$_=>1} (
1179 "/usr/local/include",
1180 "/usr/local" );
1181
1182my %OS_AddPath=(
1183# These paths are needed if the tool cannot detect them automatically
1184 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001185 "include"=>[
1186 "/Library",
1187 "/Developer/usr/include"
1188 ],
1189 "lib"=>[
1190 "/Library",
1191 "/Developer/usr/lib"
1192 ],
1193 "bin"=>[
1194 "/Developer/usr/bin"
1195 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001196 },
1197 "beos"=>{
1198 # Haiku has GCC 2.95.3 by default
1199 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001200 "include"=>[
1201 "/boot/common",
1202 "/boot/develop"
1203 ],
1204 "lib"=>[
1205 "/boot/common/lib",
1206 "/boot/system/lib",
1207 "/boot/apps"
1208 ],
1209 "bin"=>[
1210 "/boot/common/bin",
1211 "/boot/system/bin",
1212 "/boot/develop/abi"
1213 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001215);
1216
1217my %Slash_Type=(
1218 "default"=>"/",
1219 "windows"=>"\\"
1220);
1221
1222my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1223
1224# Global Variables
1225my %COMMON_LANGUAGE=(
1226 1 => "C",
1227 2 => "C" );
1228
1229my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001230my $MAX_CPPFILT_FILE_SIZE = 50000;
1231my $CPPFILT_SUPPORT_FILE;
1232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001233my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001235my $STDCXX_TESTING = 0;
1236my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001237my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001238
1239my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001240my $CheckUndefined = 0;
1241
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001242my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001243if($TargetComponent_Opt) {
1244 $TargetComponent = lc($TargetComponent_Opt);
1245}
1246else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001247{ # default: library
1248 # other components: header, system, ...
1249 $TargetComponent = "library";
1250}
1251
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001252my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001253
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001254my $SystemRoot;
1255
1256my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001257my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001258my %LOG_PATH;
1259my %DEBUG_PATH;
1260my %Cache;
1261my %LibInfo;
1262my $COMPILE_ERRORS = 0;
1263my %CompilerOptions;
1264my %CheckedDyLib;
1265my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1266
1267# Constants (#defines)
1268my %Constants;
1269my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001270my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001271
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001272# Extra Info
1273my %SymbolHeader;
1274my %KnownLibs;
1275
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001276# Templates
1277my %TemplateInstance;
1278my %BasicTemplate;
1279my %TemplateArg;
1280my %TemplateDecl;
1281my %TemplateMap;
1282
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001283# Types
1284my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001285my %SkipTypes = (
1286 "1"=>{},
1287 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001288my %CheckedTypes;
1289my %TName_Tid;
1290my %EnumMembName_Id;
1291my %NestedNameSpaces = (
1292 "1"=>{},
1293 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001294my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001295my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001296my %ClassVTable;
1297my %ClassVTable_Content;
1298my %VTableClass;
1299my %AllocableClass;
1300my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001301my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001302my %Class_SubClasses;
1303my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001304my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001305my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001306
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001307my %CheckedTypeInfo;
1308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001309# Typedefs
1310my %Typedef_BaseName;
1311my %Typedef_Tr;
1312my %Typedef_Eq;
1313my %StdCxxTypedef;
1314my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001315my %MissedBase;
1316my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001317my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001318
1319# Symbols
1320my %SymbolInfo;
1321my %tr_name;
1322my %mangled_name_gcc;
1323my %mangled_name;
1324my %SkipSymbols = (
1325 "1"=>{},
1326 "2"=>{} );
1327my %SkipNameSpaces = (
1328 "1"=>{},
1329 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001330my %AddNameSpaces = (
1331 "1"=>{},
1332 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001333my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001334my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001335my %SymbolsList_App;
1336my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001337my %Symbol_Library = (
1338 "1"=>{},
1339 "2"=>{} );
1340my %Library_Symbol = (
1341 "1"=>{},
1342 "2"=>{} );
1343my %DepSymbol_Library = (
1344 "1"=>{},
1345 "2"=>{} );
1346my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001347 "1"=>{},
1348 "2"=>{} );
1349my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001350my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001352my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001353my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001354my %Library_Needed= (
1355 "1"=>{},
1356 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001357
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001358# Extra Info
1359my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001360my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001362# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001363my %Include_Preamble = (
1364 "1"=>[],
1365 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001366my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001367my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001368my %HeaderName_Paths;
1369my %Header_Dependency;
1370my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001371my %Include_Paths = (
1372 "1"=>[],
1373 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001374my %INC_PATH_AUTODETECT = (
1375 "1"=>1,
1376 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001377my %Add_Include_Paths = (
1378 "1"=>[],
1379 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001380my %Skip_Include_Paths;
1381my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001382my %Header_ErrorRedirect;
1383my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001384my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001385my %Header_ShouldNotBeUsed;
1386my %RecursiveIncludes;
1387my %Header_Include_Prefix;
1388my %SkipHeaders;
1389my %SkipHeadersList=(
1390 "1"=>{},
1391 "2"=>{} );
1392my %SkipLibs;
1393my %Include_Order;
1394my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001395my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001396my %TUnit_Funcs;
1397my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001399my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400 "1"=>0,
1401 "2"=>0 );
1402my %AutoPreambleMode = (
1403 "1"=>0,
1404 "2"=>0 );
1405my %MinGWMode = (
1406 "1"=>0,
1407 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001408my %Cpp0xMode = (
1409 "1"=>0,
1410 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411
1412# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001413my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001414my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001415my %RegisteredSONAMEs;
1416my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001417
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001418my %CheckedArch;
1419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001420# System Objects
1421my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001422my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001423my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424
1425# System Headers
1426my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001427my @DefaultCppPaths;
1428my @DefaultGccPaths;
1429my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001430my %DefaultCppHeader;
1431my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001432my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001433
1434# Merging
1435my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001436my $Version;
1437my %AddedInt;
1438my %RemovedInt;
1439my %AddedInt_Virt;
1440my %RemovedInt_Virt;
1441my %VirtualReplacement;
1442my %ChangedTypedef;
1443my %CompatRules;
1444my %IncompleteRules;
1445my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001446my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001447my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001448my %ReturnedClass;
1449my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001450my %SourceAlternative;
1451my %SourceAlternative_B;
1452my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001453my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001455# Calling Conventions
1456my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001457 1=>{ "R"=>0, "P"=>0 },
1458 2=>{ "R"=>0, "P"=>0 }
1459);
1460
1461# ABI Dump
1462my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001463
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001464# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001465my %TargetLibs;
1466my %TargetHeaders;
1467
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001468# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001469my $OStarget = $OSgroup;
1470my %TargetTools;
1471
1472# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001473my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001474
1475# Recursion locks
1476my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001477my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001478my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001479my @RecurInclude;
1480my @RecurConstant;
1481
1482# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001483my %SystemPaths = (
1484 "include"=>[],
1485 "lib"=>[],
1486 "bin"=>[]
1487);
1488my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001489my $GCC_PATH;
1490
1491# Symbols versioning
1492my %SymVer = (
1493 "1"=>{},
1494 "2"=>{} );
1495
1496# Problem descriptions
1497my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001498my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001499my %TotalAffected;
1500
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001501# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502my $ContentID = 1;
1503my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001504my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1505my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506my $ContentSpanEnd = "</span>\n";
1507my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1508my $ContentDivEnd = "</div>\n";
1509my $Content_Counter = 0;
1510
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001511# Modes
1512my $JoinReport = 1;
1513my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001514
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001515my %Severity_Val=(
1516 "High"=>3,
1517 "Medium"=>2,
1518 "Low"=>1,
1519 "Safe"=>-1
1520);
1521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001522sub get_Modules()
1523{
1524 my $TOOL_DIR = get_dirname($0);
1525 if(not $TOOL_DIR)
1526 { # patch for MS Windows
1527 $TOOL_DIR = ".";
1528 }
1529 my @SEARCH_DIRS = (
1530 # tool's directory
1531 abs_path($TOOL_DIR),
1532 # relative path to modules
1533 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001534 # install path
1535 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536 );
1537 foreach my $DIR (@SEARCH_DIRS)
1538 {
1539 if(not is_abs($DIR))
1540 { # relative path
1541 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1542 }
1543 if(-d $DIR."/modules") {
1544 return $DIR."/modules";
1545 }
1546 }
1547 exitStatus("Module_Error", "can't find modules");
1548}
1549
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001550my %LoadedModules = ();
1551
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552sub loadModule($)
1553{
1554 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001555 if(defined $LoadedModules{$Name}) {
1556 return;
1557 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001558 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1559 if(not -f $Path) {
1560 exitStatus("Module_Error", "can't access \'$Path\'");
1561 }
1562 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001563 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001564}
1565
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001566sub readModule($$)
1567{
1568 my ($Module, $Name) = @_;
1569 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1570 if(not -f $Path) {
1571 exitStatus("Module_Error", "can't access \'$Path\'");
1572 }
1573 return readFile($Path);
1574}
1575
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001576sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001577{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001578 my $Number = $_[0];
1579 if(not $Number) {
1580 $Number = 1;
1581 }
1582 else {
1583 $Number = int($Number)+1;
1584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001585 if($Number>3) {
1586 return $Number."th";
1587 }
1588 elsif($Number==1) {
1589 return "1st";
1590 }
1591 elsif($Number==2) {
1592 return "2nd";
1593 }
1594 elsif($Number==3) {
1595 return "3rd";
1596 }
1597 else {
1598 return $Number;
1599 }
1600}
1601
1602sub search_Tools($)
1603{
1604 my $Name = $_[0];
1605 return "" if(not $Name);
1606 if(my @Paths = keys(%TargetTools))
1607 {
1608 foreach my $Path (@Paths)
1609 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001610 if(-f join_P($Path, $Name)) {
1611 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001612 }
1613 if($CrossPrefix)
1614 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001615 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001616 if(-f $Candidate) {
1617 return $Candidate;
1618 }
1619 }
1620 }
1621 }
1622 else {
1623 return "";
1624 }
1625}
1626
1627sub synch_Cmd($)
1628{
1629 my $Name = $_[0];
1630 if(not $GCC_PATH)
1631 { # GCC was not found yet
1632 return "";
1633 }
1634 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001635 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001636 return $Candidate;
1637 }
1638 return "";
1639}
1640
1641sub get_CmdPath($)
1642{
1643 my $Name = $_[0];
1644 return "" if(not $Name);
1645 if(defined $Cache{"get_CmdPath"}{$Name}) {
1646 return $Cache{"get_CmdPath"}{$Name};
1647 }
1648 my %BinUtils = map {$_=>1} (
1649 "c++filt",
1650 "objdump",
1651 "readelf"
1652 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001653 if($BinUtils{$Name} and $GCC_PATH)
1654 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001655 if(my $Dir = get_dirname($GCC_PATH)) {
1656 $TargetTools{$Dir}=1;
1657 }
1658 }
1659 my $Path = search_Tools($Name);
1660 if(not $Path and $OSgroup eq "windows") {
1661 $Path = search_Tools($Name.".exe");
1662 }
1663 if(not $Path and $BinUtils{$Name})
1664 {
1665 if($CrossPrefix)
1666 { # user-defined prefix
1667 $Path = search_Cmd($CrossPrefix."-".$Name);
1668 }
1669 }
1670 if(not $Path and $BinUtils{$Name})
1671 {
1672 if(my $Candidate = synch_Cmd($Name))
1673 { # synch with GCC
1674 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001675 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001676 if(-f $Candidate) {
1677 $Path = $Candidate;
1678 }
1679 }
1680 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001681 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001682 $Path = $Candidate;
1683 }
1684 }
1685 }
1686 if(not $Path) {
1687 $Path = search_Cmd($Name);
1688 }
1689 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001690 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001691 $Path=search_Cmd($Name.".exe");
1692 }
1693 if($Path=~/\s/) {
1694 $Path = "\"".$Path."\"";
1695 }
1696 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1697}
1698
1699sub search_Cmd($)
1700{
1701 my $Name = $_[0];
1702 return "" if(not $Name);
1703 if(defined $Cache{"search_Cmd"}{$Name}) {
1704 return $Cache{"search_Cmd"}{$Name};
1705 }
1706 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1707 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1708 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001709 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001710 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001711 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 if(-f $CmdPath)
1713 {
1714 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001715 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001716 }
1717 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1718 }
1719 }
1720 return ($Cache{"search_Cmd"}{$Name} = "");
1721}
1722
1723sub get_CmdPath_Default($)
1724{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001725 return "" if(not $_[0]);
1726 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1727 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001728 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001729 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1730}
1731
1732sub get_CmdPath_Default_I($)
1733{ # search in PATH
1734 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001735 if($Name=~/find/)
1736 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001737 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001738 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001739 }
1740 }
1741 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001742 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001743 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001744 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001745 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001747 if($OSgroup eq "windows")
1748 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001749 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001750 return $Name;
1751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001752 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001753 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001754 {
1755 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001756 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001757 }
1758 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001759 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001760}
1761
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001762sub classifyPath($)
1763{
1764 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001765 if($Path=~/[\*\+\(\[\|]/)
1766 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767 $Path=~s/\\/\\\\/g;
1768 return ($Path, "Pattern");
1769 }
1770 elsif($Path=~/[\/\\]/)
1771 { # directory or relative path
1772 return (path_format($Path, $OSgroup), "Path");
1773 }
1774 else {
1775 return ($Path, "Name");
1776 }
1777}
1778
1779sub readDescriptor($$)
1780{
1781 my ($LibVersion, $Content) = @_;
1782 return if(not $LibVersion);
1783 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1784 if(not $Content) {
1785 exitStatus("Error", "$DName is empty");
1786 }
1787 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001788 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001789 }
1790 $Content=~s/\/\*(.|\n)+?\*\///g;
1791 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001792
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001793 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1794 if($TargetVersion{$LibVersion}) {
1795 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1796 }
1797 if(not $Descriptor{$LibVersion}{"Version"}) {
1798 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1799 }
1800 if($Content=~/{RELPATH}/)
1801 {
1802 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1803 $Content =~ s/{RELPATH}/$RelDir/g;
1804 }
1805 else
1806 {
1807 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1808 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1809 }
1810 }
1811
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001812 my $DHeaders = parseTag(\$Content, "headers");
1813 if(not $DHeaders) {
1814 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1815 }
1816 elsif(lc($DHeaders) ne "none")
1817 { # append the descriptor headers list
1818 if($Descriptor{$LibVersion}{"Headers"})
1819 { # multiple descriptors
1820 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001821 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001822 else {
1823 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1824 }
1825 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1826 {
1827 if(not -e $Path) {
1828 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001829 }
1830 }
1831 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001832
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001833 if(not $CheckHeadersOnly_Opt)
1834 {
1835 my $DObjects = parseTag(\$Content, "libs");
1836 if(not $DObjects) {
1837 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1838 }
1839 elsif(lc($DObjects) ne "none")
1840 { # append the descriptor libraries list
1841 if($Descriptor{$LibVersion}{"Libs"})
1842 { # multiple descriptors
1843 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1844 }
1845 else {
1846 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1847 }
1848 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1849 {
1850 if(not -e $Path) {
1851 exitStatus("Access_Error", "can't access \'$Path\'");
1852 }
1853 }
1854 }
1855 }
1856 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1857 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001858 if(not -d $Path) {
1859 exitStatus("Access_Error", "can't access directory \'$Path\'");
1860 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001861 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001862 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001863 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001864 }
1865 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1866 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001867 if(not -d $Path) {
1868 exitStatus("Access_Error", "can't access directory \'$Path\'");
1869 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001870 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001872 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001873 }
1874 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1875 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001876 if(not -d $Path) {
1877 exitStatus("Access_Error", "can't access directory \'$Path\'");
1878 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001879 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001880 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001881 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001882 $TargetTools{$Path}=1;
1883 }
1884 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1885 $CrossPrefix = $Prefix;
1886 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001887 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001888 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1889 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 if(not -d $Path) {
1891 exitStatus("Access_Error", "can't access directory \'$Path\'");
1892 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001893 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001895 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001897 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1899 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001900 if(not -d $Path) {
1901 exitStatus("Access_Error", "can't access directory \'$Path\'");
1902 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001903 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001904 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001905 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906 }
1907 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001908 { # skip some auto-generated include paths
1909 if(not is_abs($Path))
1910 {
1911 if(my $P = abs_path($Path)) {
1912 $Path = $P;
1913 }
1914 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001915 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001916 }
1917 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001918 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 my ($CPath, $Type) = classifyPath($Path);
1920 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001921 }
1922 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001923 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1924 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001925 if($Option!~/\A\-(Wl|l|L)/)
1926 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001927 $CompilerOptions{$LibVersion} .= " ".$Option;
1928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 }
1930 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1931 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1932 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001933 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001934
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001935 my ($CPath, $Type) = classifyPath($Path);
1936 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001937 }
1938 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1939 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1940 {
1941 my ($CPath, $Type) = classifyPath($Path);
1942 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1943 }
1944 if(my $DDefines = parseTag(\$Content, "defines"))
1945 {
1946 if($Descriptor{$LibVersion}{"Defines"})
1947 { # multiple descriptors
1948 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1949 }
1950 else {
1951 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1952 }
1953 }
1954 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1955 {
1956 if($Order=~/\A(.+):(.+)\Z/) {
1957 $Include_Order{$LibVersion}{$1} = $2;
1958 }
1959 }
1960 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1961 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001962 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001963 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1964 }
1965 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1966 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001967 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001968 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1969 }
1970 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1971 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1972 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001973 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1974 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001976 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1977 $SkipConstants{$LibVersion}{$Constant} = 1;
1978 }
1979 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1980 {
1981 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001982 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001983 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1984 }
1985 else {
1986 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1987 }
1988 }
1989}
1990
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001991sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001992{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001993 my $CodeRef = shift(@_);
1994 my $Tag = shift(@_);
1995 if(not $Tag or not $CodeRef) {
1996 return undef;
1997 }
1998 my $Sp = 0;
1999 if(@_) {
2000 $Sp = shift(@_);
2001 }
2002 my $Start = index(${$CodeRef}, "<$Tag>");
2003 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002004 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002005 my $End = index(${$CodeRef}, "</$Tag>");
2006 if($End!=-1)
2007 {
2008 my $TS = length($Tag)+3;
2009 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2010 substr($Content, 0, $TS-1, ""); # cut start tag
2011 substr($Content, -$TS, $TS, ""); # cut end tag
2012 if(not $Sp)
2013 {
2014 $Content=~s/\A\s+//g;
2015 $Content=~s/\s+\Z//g;
2016 }
2017 if(substr($Content, 0, 1) ne "<") {
2018 $Content = xmlSpecChars_R($Content);
2019 }
2020 return $Content;
2021 }
2022 }
2023 return undef;
2024}
2025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002026sub getInfo($)
2027{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002028 my $DumpPath = $_[0];
2029 return if(not $DumpPath or not -f $DumpPath);
2030
2031 readTUDump($DumpPath);
2032
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002033 # processing info
2034 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002035
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002036 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002037 setAnonTypedef_All();
2038 }
2039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002040 getTypeInfo_All();
2041 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002042 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002043 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002044 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002045
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002046 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002047 %LibInfo = ();
2048 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002049 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002051 %TemplateDecl = ();
2052 %StdCxxTypedef = ();
2053 %MissedTypedef = ();
2054 %Typedef_Tr = ();
2055 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002056 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002057
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002058 # clean cache
2059 delete($Cache{"getTypeAttr"});
2060 delete($Cache{"getTypeDeclId"});
2061
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002062 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002063 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002064 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002065 }
2066 else
2067 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002068 if($BinaryOnly and not $ExtendedCheck)
2069 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002070 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002071 }
2072 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002073 remove_Unused($Version, "Extended");
2074 }
2075 }
2076
2077 if($CheckInfo)
2078 {
2079 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2080 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2081 }
2082
2083 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2084 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002086 }
2087
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002088 if($Debug) {
2089 # debugMangling($Version);
2090 }
2091}
2092
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002093sub readTUDump($)
2094{
2095 my $DumpPath = $_[0];
2096
2097 open(TU_DUMP, $DumpPath);
2098 local $/ = undef;
2099 my $Content = <TU_DUMP>;
2100 close(TU_DUMP);
2101
2102 unlink($DumpPath);
2103
2104 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002105 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002106
2107 # clean memory
2108 undef $Content;
2109
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002110 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002111
2112 foreach (0 .. $#Lines)
2113 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002114 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002115 { # get a number and attributes of a node
2116 next if(not $NodeType{$2});
2117 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002118 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002119 }
2120
2121 # clean memory
2122 delete($Lines[$_]);
2123 }
2124
2125 # clean memory
2126 undef @Lines;
2127}
2128
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002129sub simplifyConstants()
2130{
2131 foreach my $Constant (keys(%{$Constants{$Version}}))
2132 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002133 if(defined $Constants{$Version}{$Constant}{"Header"})
2134 {
2135 my $Value = $Constants{$Version}{$Constant}{"Value"};
2136 if(defined $EnumConstants{$Version}{$Value}) {
2137 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2138 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002139 }
2140 }
2141}
2142
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002143sub simplifyNames()
2144{
2145 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2146 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002147 if($Typedef_Eq{$Version}{$Base}) {
2148 next;
2149 }
2150 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2151 if($#Translations==0)
2152 {
2153 if(length($Translations[0])<=length($Base)) {
2154 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2155 }
2156 }
2157 else
2158 { # select most appropriate
2159 foreach my $Tr (@Translations)
2160 {
2161 if($Base=~/\A\Q$Tr\E/)
2162 {
2163 $Typedef_Eq{$Version}{$Base} = $Tr;
2164 last;
2165 }
2166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002167 }
2168 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002169 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002170 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002171 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002172 if(not $TypeName) {
2173 next;
2174 }
2175 next if(index($TypeName,"<")==-1);# template instances only
2176 if($TypeName=~/>(::\w+)+\Z/)
2177 { # skip unused types
2178 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002180 foreach my $Base (sort {length($b)<=>length($a)}
2181 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002182 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002183 next if(not $Base);
2184 next if(index($TypeName,$Base)==-1);
2185 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002186 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002187 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002188 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2189 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2190 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002191 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002192 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2193 {
2194 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2195 {
2196 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2197 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002198 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002199 }
2200 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002203 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002204 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002205 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2206 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002207 }
2208}
2209
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002210sub setAnonTypedef_All()
2211{
2212 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2213 {
2214 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2215 {
2216 if(isAnon(getNameByInfo($InfoId))) {
2217 $TypedefToAnon{getTypeId($InfoId)} = 1;
2218 }
2219 }
2220 }
2221}
2222
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002223sub setTemplateParams_All()
2224{
2225 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2226 {
2227 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2228 setTemplateParams($_);
2229 }
2230 }
2231}
2232
2233sub setTemplateParams($)
2234{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002235 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002236 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002237 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002238 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002239 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002240 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002241 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002242 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002243 setTemplateInstParams($_[0], $TmplInst_Id);
2244 }
2245 }
2246
2247 $BasicTemplate{$Version}{$Tid} = $_[0];
2248
2249 if(my $Prms = getTreeAttr_Prms($_[0]))
2250 {
2251 if(my $Valu = getTreeAttr_Valu($Prms))
2252 {
2253 my $Vector = getTreeVec($Valu);
2254 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2255 {
2256 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2257 {
2258 if(my $Name = getNameByInfo($Val))
2259 {
2260 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2261 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2262 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2263 }
2264 else {
2265 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2266 }
2267 }
2268 }
2269 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002271 }
2272 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002273 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002274 {
2275 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2276 {
2277 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002278 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002279 }
2280 }
2281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002282}
2283
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002284sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002285{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002286 my ($Tmpl, $Inst) = @_;
2287
2288 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002289 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002290 my ($Params_InfoId, $ElemId) = ();
2291 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2292 $Params_InfoId = $1;
2293 }
2294 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2295 $ElemId = $1;
2296 }
2297 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002298 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002299 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2300 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2301 {
2302 my ($PPos, $PTypeId) = ($1, $2);
2303 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2304 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002305 if($PType eq "template_type_parm") {
2306 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002307 }
2308 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002309 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2310 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002311 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002312 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002313 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002314 else
2315 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002316 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002317 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002319 }
2320 }
2321 }
2322}
2323
2324sub getTypeDeclId($)
2325{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002326 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002327 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002328 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2329 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2330 }
2331 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2332 {
2333 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2334 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2335 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002337 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002338 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002339}
2340
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341sub getTypeInfo_All()
2342{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002343 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002344 { # support for GCC < 4.5
2345 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2346 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2347 # FIXME: check GCC versions
2348 addMissedTypes_Pre();
2349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002350
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002351 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002352 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002353 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2354 if($IType=~/_type\Z/ and $IType ne "function_type"
2355 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002356 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002357 }
2358 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002359
2360 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002361 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002362 "Name" => "...",
2363 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002364 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002365 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002366 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367
2368 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002369 { # support for GCC < 4.5
2370 addMissedTypes_Post();
2371 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002372
2373 if($ADD_TMPL_INSTANCES)
2374 {
2375 # templates
2376 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2377 {
2378 if(defined $TemplateMap{$Version}{$Tid}
2379 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2380 {
2381 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2382 {
2383 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2384 {
2385 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2386 {
2387 if(my %MAttr = getTypeAttr($MembTypeId))
2388 {
2389 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2390 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2391 }
2392 }
2393 }
2394 }
2395 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2396 {
2397 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2398 {
2399 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2400
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002401 if($NBid ne $Bid
2402 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002403 {
2404 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2405 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2406 }
2407 }
2408 }
2409 }
2410 }
2411 }
2412}
2413
2414sub createType($$)
2415{
2416 my ($Attr, $LibVersion) = @_;
2417 my $NewId = ++$MAX_ID;
2418
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002419 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002420 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002421 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002422
2423 return "$NewId";
2424}
2425
2426sub instType($$$)
2427{ # create template instances
2428 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002429
2430 if(not $TypeInfo{$LibVersion}{$Tid}) {
2431 return undef;
2432 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002433 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2434
2435 foreach my $Key (sort keys(%{$Map}))
2436 {
2437 if(my $Val = $Map->{$Key})
2438 {
2439 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2440
2441 if(defined $Attr->{"NameSpace"}) {
2442 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2443 }
2444 foreach (keys(%{$Attr->{"TParam"}})) {
2445 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2446 }
2447 }
2448 else
2449 { # remove absent
2450 # _Traits, etc.
2451 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002452 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002453 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2454 }
2455 foreach (keys(%{$Attr->{"TParam"}}))
2456 {
2457 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2458 delete($Attr->{"TParam"}{$_});
2459 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002460 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002461 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2462 }
2463 }
2464 }
2465 }
2466
2467 my $Tmpl = 0;
2468
2469 if(defined $Attr->{"TParam"})
2470 {
2471 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2472 {
2473 my $PName = $Attr->{"TParam"}{$_}{"name"};
2474
2475 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2476 {
2477 my %Base = get_BaseType($PTid, $LibVersion);
2478
2479 if($Base{"Type"} eq "TemplateParam"
2480 or defined $Base{"Template"})
2481 {
2482 $Tmpl = 1;
2483 last
2484 }
2485 }
2486 }
2487 }
2488
2489 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2490 return "$Id";
2491 }
2492 else
2493 {
2494 if(not $Tmpl) {
2495 delete($Attr->{"Template"});
2496 }
2497
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002498 my $New = createType($Attr, $LibVersion);
2499
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002500 my %EMap = ();
2501 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2502 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2503 }
2504 foreach (keys(%{$Map})) {
2505 $EMap{$_} = $Map->{$_};
2506 }
2507
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002508 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2509 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002510 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002511 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002512 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002513 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002514 {
2515 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2516
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002517 if($NBid ne $Bid
2518 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002519 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002520 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2521 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002522 }
2523 }
2524 }
2525
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002526 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002527 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002528 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2529 {
2530 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2531 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2532 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002533 }
2534 }
2535
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002536 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002537 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002538 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2539 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002540 }
2541 }
2542
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002543 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2544 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002545 }
2546
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002547 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002549}
2550
2551sub addMissedTypes_Pre()
2552{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002553 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002554 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2555 { # detecting missed typedefs
2556 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2557 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002558 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002559 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002560 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002561 if($TypeType eq "Unknown")
2562 { # template_type_parm
2563 next;
2564 }
2565 my $TypeDeclId = getTypeDeclId($TypeId);
2566 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2567 my $TypedefName = getNameByInfo($MissedTDid);
2568 next if(not $TypedefName);
2569 next if($TypedefName eq "__float80");
2570 next if(isAnon($TypedefName));
2571 if(not $TypeDeclId
2572 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002573 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002574 }
2575 }
2576 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002577 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002578 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002579 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002580 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002582 next;
2583 }
2584 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002585 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002586 if(not $TypedefName) {
2587 next;
2588 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002589 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002590 my %MissedInfo = ( # typedef info
2591 "Name" => $TypedefName,
2592 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002593 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002594 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002595 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 my ($H, $L) = getLocation($MissedTDid);
2597 $MissedInfo{"Header"} = $H;
2598 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002599 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 { # other types
2601 next;
2602 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002603 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002604 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605 next;
2606 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002607 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002608 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002609 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002611 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002613 next;
2614 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002615 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 next;
2617 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002618 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002619 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 next;
2621 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002622 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002623 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002624 next;
2625 }
2626 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002627
2628 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002631 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002632 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002634 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002635
2636 # add missed & remove other
2637 $TypeInfo{$Version} = \%AddTypes;
2638 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639}
2640
2641sub addMissedTypes_Post()
2642{
2643 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2644 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002645 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2646 {
2647 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2648 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2649 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2650 }
2651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 }
2653}
2654
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002655sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002657 my $TypeId = $_[0];
2658 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2659 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002661 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002663}
2664
2665sub getArraySize($$)
2666{
2667 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002668 if(my $Size = getSize($TypeId))
2669 {
2670 my $Elems = $Size/$BYTE_SIZE;
2671 while($BaseName=~s/\s*\[(\d+)\]//) {
2672 $Elems/=$1;
2673 }
2674 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2675 {
2676 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2677 $Elems/=$BasicSize;
2678 }
2679 }
2680 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002681 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002682 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683}
2684
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002685sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002686{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002687 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002688 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002689 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2690 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002691 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002692 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2693 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2694 if(not $NodeType)
2695 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002696 return ();
2697 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002698 if($NodeType eq "tree_vec")
2699 {
2700 if($Pos!=$#Positions)
2701 { # select last vector of parameters ( ns<P1>::type<P2> )
2702 next;
2703 }
2704 }
2705 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2706 foreach my $P (@Params)
2707 {
2708 if($P eq "") {
2709 return ();
2710 }
2711 elsif($P ne "\@skip\@") {
2712 @TmplParams = (@TmplParams, $P);
2713 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002714 }
2715 }
2716 return @TmplParams;
2717}
2718
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002719sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002720{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002721 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002722 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002723 if(defined $TypeInfo{$Version}{$TypeId}
2724 and $TypeInfo{$Version}{$TypeId}{"Name"})
2725 { # already created
2726 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002727 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002728 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2729 { # incomplete type
2730 return ();
2731 }
2732 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2733
2734 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002735 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002736
2737 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2738 {
2739 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2740 {
2741 if($Info=~/qual[ ]*:/)
2742 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002743 my $NewId = ++$MAX_ID;
2744
2745 $MissedBase{$Version}{$TypeId} = "$NewId";
2746 $MissedBase_R{$Version}{$NewId} = $TypeId;
2747 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2748 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002749 }
2750 }
2751 $TypeAttr{"Type"} = "Typedef";
2752 }
2753 else {
2754 $TypeAttr{"Type"} = getTypeType($TypeId);
2755 }
2756
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002757 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2758 {
2759 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2760 { # local code
2761 return ();
2762 }
2763 }
2764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002765 if($TypeAttr{"Type"} eq "Unknown") {
2766 return ();
2767 }
2768 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2769 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002770 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002771 if(my $TName = $TypeAttr{"Name"})
2772 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002773 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002774 $TName_Tid{$Version}{$TName} = $TypeId;
2775 return %TypeAttr;
2776 }
2777 else {
2778 return ();
2779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002780 }
2781 elsif($TypeAttr{"Type"} eq "Array")
2782 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002783 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2784 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002785 return ();
2786 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002787 if(my $Algn = getAlgn($TypeId)) {
2788 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2789 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002790 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002791 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002792 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002793 if(not $BTAttr{"Name"}) {
2794 return ();
2795 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002796 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002797 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002798 if(my $Size = getSize($TypeId)) {
2799 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2800 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002801 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002802 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2803 }
2804 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002805 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002807 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 else
2809 {
2810 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002811 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002812 $TypeAttr{"Name"} = $1."[]".$2;
2813 }
2814 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002815 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002817 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002818 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002819 if($BTAttr{"Header"}) {
2820 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002821 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002822 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002823 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2824 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002825 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002826 return ();
2827 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002828 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002829 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002830 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002831 if($TypeAttr{"Name"})
2832 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002833 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002834
2835 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2836 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002837 { # NOTE: register only one int: with built-in decl
2838 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2839 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2840 }
2841 }
2842 return %TypeAttr;
2843 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002844 else {
2845 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002847 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002848 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2849 {
2850 %TypeAttr = getTrivialTypeAttr($TypeId);
2851 if($TypeAttr{"Name"})
2852 {
2853 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2854 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2855 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2856 }
2857 return %TypeAttr;
2858 }
2859 else {
2860 return ();
2861 }
2862 }
2863 elsif($TypeAttr{"Type"} eq "SizeOf")
2864 {
2865 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2866 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2867 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2868 if($TypeAttr{"Name"})
2869 {
2870 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2871 return %TypeAttr;
2872 }
2873 else {
2874 return ();
2875 }
2876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002877 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002878 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002879 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2880 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002881 return ();
2882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002883 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002884 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002885 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002887 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002888 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002889 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002891 }
2892 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002893 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002894 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002895 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002896 return ();
2897 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002898 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002899 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002900 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002901 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002902 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002903 }
2904 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002905 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 {
2907 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002908 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002909 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002910 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002911 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2912 }
2913 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002914 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002915 }
2916 }
2917 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002918 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002919 }
2920 if($TypeAttr{"Type"} eq "Typedef")
2921 {
2922 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002923
2924 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2925 return ();
2926 }
2927
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002928 if(isAnon($TypeAttr{"Name"}))
2929 { # anon typedef to anon type: ._N
2930 return ();
2931 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002932
2933 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2934 { # artificial typedef of "struct X" to "X"
2935 $TypeAttr{"Artificial"} = 1;
2936 }
2937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002938 if(my $NS = getNameSpace($TypeDeclId))
2939 {
2940 my $TypeName = $TypeAttr{"Name"};
2941 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2942 { # "some_type" is the typedef to "struct some_type" in C++
2943 if($3) {
2944 $TypeAttr{"Name"} = $3."::".$TypeName;
2945 }
2946 }
2947 else
2948 {
2949 $TypeAttr{"NameSpace"} = $NS;
2950 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002951
2952 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2953 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2954 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 if($BTAttr{"NameSpace"}
2956 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002957 { # types like "std::fpos<__mbstate_t>" are
2958 # not covered by typedefs in the TU dump
2959 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2961 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002962 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002963 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002964 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002966 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002967 }
2968 }
2969 }
2970 }
2971 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002972 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002973 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002974 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002975 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2976 { # typedef int*const TYPEDEF; // first
2977 # int foo(TYPEDEF p); // const is optimized out
2978 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2979 if($BTAttr{"Name"}=~/</)
2980 {
2981 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2982 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002984 }
2985 }
2986 }
2987 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2988 }
2989 if(not $TypeAttr{"Size"})
2990 {
2991 if($TypeAttr{"Type"} eq "Pointer") {
2992 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2993 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002994 elsif($BTAttr{"Size"}) {
2995 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002996 }
2997 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002998 if(my $Algn = getAlgn($TypeId)) {
2999 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3000 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003001 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003002 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3003 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003004 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003005 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003006 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003007 { # typedef to "class Class"
3008 # should not be registered in TName_Tid
3009 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3010 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003012 }
3013 return %TypeAttr;
3014 }
3015}
3016
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003017sub getTreeVec($)
3018{
3019 my %Vector = ();
3020 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3021 {
3022 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3023 { # string length is N-1 because of the null terminator
3024 $Vector{$1} = $2;
3025 }
3026 }
3027 return \%Vector;
3028}
3029
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030sub get_TemplateParam($$)
3031{
3032 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003033 return () if(not $Type_Id);
3034 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3035 return () if(not $NodeType);
3036 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003037 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003038 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003039 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 my $Num = getNodeIntCst($Type_Id);
3041 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003042 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003043 }
3044 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003045 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 }
3047 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003048 elsif($NodeType eq "string_cst") {
3049 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003051 elsif($NodeType eq "tree_vec")
3052 {
3053 my $Vector = getTreeVec($Type_Id);
3054 my @Params = ();
3055 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3056 {
3057 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3058 push(@Params, $P2);
3059 }
3060 }
3061 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003062 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003063 elsif($NodeType eq "parm_decl")
3064 {
3065 (getNameByInfo($Type_Id));
3066 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003067 else
3068 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003069 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003070 my $PName = $ParamAttr{"Name"};
3071 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003072 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003073 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003074 if($PName=~/\>/)
3075 {
3076 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003077 $PName = $Cover;
3078 }
3079 }
3080 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003081 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003082 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3083 # template<typename _Key, typename _Compare = std::less<_Key>
3084 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3085 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3086 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3087 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003088 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003089 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003090 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003091 }
3092}
3093
3094sub cover_stdcxx_typedef($)
3095{
3096 my $TypeName = $_[0];
3097 if(my @Covers = sort {length($a)<=>length($b)}
3098 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3099 { # take the shortest typedef
3100 # FIXME: there may be more than
3101 # one typedefs to the same type
3102 return $Covers[0];
3103 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003104 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003105 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3106 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3107 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003108 if(my $Cover = $Covers[0])
3109 {
3110 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3111 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003113 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003114 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003115}
3116
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003117sub getNodeIntCst($)
3118{
3119 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003120 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003121 if($EnumMembName_Id{$Version}{$CstId}) {
3122 return $EnumMembName_Id{$Version}{$CstId};
3123 }
3124 elsif((my $Value = getTreeValue($CstId)) ne "")
3125 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003126 if($Value eq "0")
3127 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003128 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003129 return "false";
3130 }
3131 else {
3132 return "0";
3133 }
3134 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003135 elsif($Value eq "1")
3136 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003137 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003138 return "true";
3139 }
3140 else {
3141 return "1";
3142 }
3143 }
3144 else {
3145 return $Value;
3146 }
3147 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003148 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003149}
3150
3151sub getNodeStrCst($)
3152{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003153 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3154 {
3155 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003156 {
3157 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3158 { # string length is N-1 because of the null terminator
3159 return substr($1, 0, $2-1);
3160 }
3161 else
3162 { # identifier_node
3163 return substr($1, 0, $2);
3164 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003166 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003167 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003168}
3169
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003170sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003172 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3174 if($Type eq "FieldPtr") {
3175 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3176 }
3177 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3178 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003179 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003180 if($Type eq "MethodPtr")
3181 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003182 if(my $Size = getSize($TypeId))
3183 {
3184 $Size/=$BYTE_SIZE;
3185 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003187 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003188 if(my $Algn = getAlgn($TypeId)) {
3189 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003191 # Return
3192 if($Type eq "FieldPtr")
3193 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003194 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003195 if($ReturnAttr{"Name"}) {
3196 $MemPtrName .= $ReturnAttr{"Name"};
3197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003198 $TypeAttr{"Return"} = $PtrId;
3199 }
3200 else
3201 {
3202 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3203 {
3204 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003205 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3206 if(not $ReturnAttr{"Name"})
3207 { # templates
3208 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003210 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003211 $TypeAttr{"Return"} = $ReturnTypeId;
3212 }
3213 }
3214 # Class
3215 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3216 {
3217 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003218 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003219 if($Class{"Name"}) {
3220 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3221 }
3222 else {
3223 $MemPtrName .= " (*)";
3224 }
3225 }
3226 else {
3227 $MemPtrName .= " (*)";
3228 }
3229 # Parameters
3230 if($Type eq "FuncPtr"
3231 or $Type eq "MethodPtr")
3232 {
3233 my @ParamTypeName = ();
3234 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3235 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003236 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003237 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003238 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003239 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003240 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3241 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003242 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003243 my $PTypeId = $1;
3244 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003245 if(not $ParamAttr{"Name"})
3246 { # templates (template_type_parm), etc.
3247 return ();
3248 }
3249 if($ParamAttr{"Name"} eq "void") {
3250 last;
3251 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003252 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003253 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003254 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003255 push(@ParamTypeName, $ParamAttr{"Name"});
3256 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003257 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3258 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003259 }
3260 else {
3261 last;
3262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003263 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003264 else {
3265 last;
3266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003267 }
3268 }
3269 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3270 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003271 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003272 return %TypeAttr;
3273}
3274
3275sub getTreeTypeName($)
3276{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003277 my $TypeId = $_[0];
3278 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003279 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003280 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003281 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003282 if(my $Name = getNameByInfo($TypeId))
3283 { # bit_size_type
3284 return $Name;
3285 }
3286 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003287 return "unsigned int";
3288 }
3289 else {
3290 return "int";
3291 }
3292 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003293 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003294 return getNameByInfo($1);
3295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003296 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003297 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298}
3299
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003300sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003301{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003302 my $Ptd = pointTo($_[0]);
3303 return 0 if(not $Ptd);
3304 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003305 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003306 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3307 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308 }
3309 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003310 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3311 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003312 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003313 if($InfoT1 eq "pointer_type"
3314 and $InfoT2 eq "function_type") {
3315 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003316 }
3317 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003318 return 0;
3319}
3320
3321sub isMethodPtr($)
3322{
3323 my $Ptd = pointTo($_[0]);
3324 return 0 if(not $Ptd);
3325 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3326 {
3327 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3328 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3329 and $Info=~/ ptrmem /) {
3330 return 1;
3331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003332 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003333 return 0;
3334}
3335
3336sub isFieldPtr($)
3337{
3338 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3339 {
3340 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3341 and $Info=~/ ptrmem /) {
3342 return 1;
3343 }
3344 }
3345 return 0;
3346}
3347
3348sub pointTo($)
3349{
3350 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3351 {
3352 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3353 return $1;
3354 }
3355 }
3356 return "";
3357}
3358
3359sub getTypeTypeByTypeId($)
3360{
3361 my $TypeId = $_[0];
3362 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3363 {
3364 my $NType = $NodeType{$TType};
3365 if($NType eq "Intrinsic") {
3366 return $NType;
3367 }
3368 elsif(isFuncPtr($TypeId)) {
3369 return "FuncPtr";
3370 }
3371 elsif(isMethodPtr($TypeId)) {
3372 return "MethodPtr";
3373 }
3374 elsif(isFieldPtr($TypeId)) {
3375 return "FieldPtr";
3376 }
3377 elsif($NType ne "Other") {
3378 return $NType;
3379 }
3380 }
3381 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003382}
3383
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003384my %UnQual = (
3385 "r"=>"restrict",
3386 "v"=>"volatile",
3387 "c"=>"const",
3388 "cv"=>"const volatile"
3389);
3390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003391sub getQual($)
3392{
3393 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003394 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3395 {
3396 my ($Qual, $To) = ();
3397 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3398 $Qual = $UnQual{$1};
3399 }
3400 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3401 $To = $1;
3402 }
3403 if($Qual and $To) {
3404 return ($Qual, $To);
3405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003406 }
3407 return ();
3408}
3409
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003410sub getQualType($)
3411{
3412 if($_[0] eq "const volatile") {
3413 return "ConstVolatile";
3414 }
3415 return ucfirst($_[0]);
3416}
3417
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003418sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003419{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003420 my $TypeId = $_[0];
3421 my $TypeDeclId = getTypeDeclId($TypeId);
3422 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003423 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003424 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3425 return "Typedef";
3426 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003427 }
3428 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3429 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003430 if(($Qual or $To) and $TypeDeclId
3431 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003432 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003433 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003434 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003435 elsif(not $MissedBase_R{$Version}{$TypeId}
3436 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003437 return "Typedef";
3438 }
3439 elsif($Qual)
3440 { # qualified types
3441 return getQualType($Qual);
3442 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003443
3444 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3445 { # typedef struct { ... } name
3446 $TypeTypedef{$Version}{$TypeId} = $1;
3447 }
3448
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003449 my $TypeType = getTypeTypeByTypeId($TypeId);
3450 if($TypeType eq "Struct")
3451 {
3452 if($TypeDeclId
3453 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3454 return "Template";
3455 }
3456 }
3457 return $TypeType;
3458}
3459
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003460sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003461{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003462 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003463 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003464 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3465 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3466 return 0;
3467 }
3468 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3469 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003470 if(my $TDid = getTypeDeclId($_[0]))
3471 {
3472 if(getTypeId($TDid) eq $_[0]
3473 and getNameByInfo($TDid))
3474 {
3475 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3476 return $1;
3477 }
3478 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003479 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003480 }
3481 }
3482 return 0;
3483}
3484
3485sub selectBaseType($)
3486{
3487 my $TypeId = $_[0];
3488 if(defined $MissedTypedef{$Version}{$TypeId})
3489 { # add missed typedefs
3490 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3491 return ($TypeId, "");
3492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003493 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003494 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3495 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003496
3497 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3498 my $MB = $MissedBase{$Version}{$TypeId};
3499
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003500 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003501 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003502 and (getTypeId($1) ne $TypeId)
3503 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003504 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003505 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003506 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003507 elsif($MB)
3508 { # add base
3509 return ($MB, "");
3510 }
3511 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003512 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003513 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003514 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003515 elsif($Qual or $To)
3516 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003517 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003518 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003519 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003520 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003521 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003522 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003524 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003525 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003527 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003528 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003530 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003531 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003532 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003533 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003534 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003536 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003537
3538 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003539}
3540
3541sub getSymbolInfo_All()
3542{
3543 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3544 { # reverse order
3545 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003546 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003547 }
3548 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003549
3550 if($ADD_TMPL_INSTANCES)
3551 {
3552 # templates
3553 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3554 {
3555 my %Map = ();
3556
3557 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3558 {
3559 if(defined $TemplateMap{$Version}{$ClassId})
3560 {
3561 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3562 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3563 }
3564 }
3565 }
3566
3567 if(defined $TemplateMap{$Version}{$Sid})
3568 {
3569 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3570 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3571 }
3572 }
3573
3574 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3575 {
3576 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3577 {
3578 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3579 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3580 }
3581 }
3582 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3583 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3584 }
3585 }
3586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003587}
3588
3589sub getVarInfo_All()
3590{
3591 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3592 { # reverse order
3593 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003594 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003595 }
3596 }
3597}
3598
3599sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003600 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003601}
3602
3603sub getVarInfo($)
3604{
3605 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003606 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003607 {
3608 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3609 if($NSInfoType and $NSInfoType eq "function_decl") {
3610 return;
3611 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003612 }
3613 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3614 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3615 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3616 delete($SymbolInfo{$Version}{$InfoId});
3617 return;
3618 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003619 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003620 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003621 delete($SymbolInfo{$Version}{$InfoId});
3622 return;
3623 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003624 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3625 delete($SymbolInfo{$Version}{$InfoId});
3626 return;
3627 }
3628 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003629 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3630 {
3631 if($OSgroup eq "windows")
3632 { # cut the offset
3633 $MnglName=~s/\@\d+\Z//g;
3634 }
3635 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003637 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003638 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003639 { # validate mangled name
3640 delete($SymbolInfo{$Version}{$InfoId});
3641 return;
3642 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003643 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003644 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003645 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003646 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003647 }
3648 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3649 { # non-public global data
3650 delete($SymbolInfo{$Version}{$InfoId});
3651 return;
3652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003653 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003654 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003655 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003656 if(not defined $TypeInfo{$Version}{$Rid}
3657 or not $TypeInfo{$Version}{$Rid}{"Name"})
3658 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003659 delete($SymbolInfo{$Version}{$InfoId});
3660 return;
3661 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003662 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3663 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003664 if(defined $Val) {
3665 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003667 }
3668 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003669 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3670 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003671 if(not defined $TypeInfo{$Version}{$ClassId}
3672 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3673 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003674 delete($SymbolInfo{$Version}{$InfoId});
3675 return;
3676 }
3677 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003678 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3679 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003680 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003681 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003683 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003684 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003685 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003686 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003687 if(not $CheckHeadersOnly)
3688 {
3689 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3690 {
3691 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3692 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3693 {
3694 if(link_symbol($ShortName, $Version, "-Deps"))
3695 { # "const" global data is mangled as _ZL... in the TU dump
3696 # but not mangled when compiling a C shared library
3697 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3698 }
3699 }
3700 }
3701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003702 if($COMMON_LANGUAGE{$Version} eq "C++")
3703 {
3704 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3705 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003706 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003707 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3708 }
3709 }
3710 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3711 { # try to mangle symbol (link with libraries)
3712 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3713 }
3714 if($OStarget eq "windows")
3715 {
3716 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3717 { # link MS C++ symbols from library with GCC symbols from headers
3718 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3719 }
3720 }
3721 }
3722 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3723 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3724 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003725 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3726 {
3727 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3728 { # non-target symbols
3729 delete($SymbolInfo{$Version}{$InfoId});
3730 return;
3731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003732 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003733 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3734 {
3735 if(defined $MissedTypedef{$Version}{$Rid})
3736 {
3737 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3738 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3739 }
3740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003741 }
3742 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003743 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003744 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3745 }
3746 if($ShortName=~/\A(_Z|\?)/) {
3747 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3748 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003749
3750 if($ExtraDump) {
3751 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003753}
3754
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003755sub isConstType($$)
3756{
3757 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003758 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003759 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003760 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003761 }
3762 return ($Base{"Type"} eq "Const");
3763}
3764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003765sub getTrivialName($$)
3766{
3767 my ($TypeInfoId, $TypeId) = @_;
3768 my %TypeAttr = ();
3769 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3770 if(not $TypeAttr{"Name"}) {
3771 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3772 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003773 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003774 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003775 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003776 if(isAnon($TypeAttr{"Name"}))
3777 {
3778 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003779 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003780 { # searching for a first not anon scope
3781 if($NSId eq $NameSpaceId) {
3782 last;
3783 }
3784 else
3785 {
3786 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3787 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003788 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003789 last;
3790 }
3791 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003792 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003793 }
3794 }
3795 else
3796 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003797 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003798 {
3799 if($NameSpaceId ne $TypeId) {
3800 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003802 }
3803 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003804 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003805 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3806 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003807 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003808 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003809 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003810 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003811 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003812 if($TypeAttr{"NameSpace"}) {
3813 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003815 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003816 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3817 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003818 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003819 if(my @TParams = getTParams($TypeId, "Type")) {
3820 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3821 }
3822 else {
3823 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003825 }
3826 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3827}
3828
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003829sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003830{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003831 my $TypeId = $_[0];
3832 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003833
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003834 my %TypeAttr = ();
3835
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003836 if($TemplateDecl{$Version}{$TypeId})
3837 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003838 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003839 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003840
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003841 setTypeAccess($TypeId, \%TypeAttr);
3842 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3843 if(isBuiltIn($TypeAttr{"Header"}))
3844 {
3845 delete($TypeAttr{"Header"});
3846 delete($TypeAttr{"Line"});
3847 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003848
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003849 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003850 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3851 if(not $TypeAttr{"Name"}) {
3852 return ();
3853 }
3854 if(not $TypeAttr{"NameSpace"}) {
3855 delete($TypeAttr{"NameSpace"});
3856 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003857
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003858 if($TypeAttr{"Type"} eq "Intrinsic")
3859 {
3860 if(defined $TypeAttr{"Header"})
3861 {
3862 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3863 { # support for SUSE 11.2
3864 # integer_type has srcp dump{1-2}.i
3865 delete($TypeAttr{"Header"});
3866 }
3867 }
3868 }
3869
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003870 my $Tmpl = undef;
3871
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003872 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003873 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003874 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3875
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003876 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003877 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003878 foreach my $Pos (0 .. $#TParams)
3879 {
3880 my $Val = $TParams[$Pos];
3881 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3882
3883 if(not defined $TypeAttr{"Template"})
3884 {
3885 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3886
3887 if($Base{"Type"} eq "TemplateParam"
3888 or defined $Base{"Template"}) {
3889 $TypeAttr{"Template"} = 1;
3890 }
3891 }
3892
3893 if($Tmpl)
3894 {
3895 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3896 {
3897 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3898
3899 if($Val eq $Arg) {
3900 $TypeAttr{"Template"} = 1;
3901 }
3902 }
3903 }
3904 }
3905
3906 if($Tmpl)
3907 {
3908 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3909 {
3910 if($Pos>$#TParams)
3911 {
3912 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3913 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3914 }
3915 }
3916 }
3917 }
3918
3919 if($ADD_TMPL_INSTANCES)
3920 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003921 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003922 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003923 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003924 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003925 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003926 {
3927 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3928 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3929 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003930 }
3931 if(not getTreeAttr_Binf($TypeId))
3932 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003933 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3934 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3935 }
3936 }
3937 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003938 }
3939 }
3940 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003941
3942 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3943
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003944 if(my $Size = getSize($TypeId))
3945 {
3946 $Size = $Size/$BYTE_SIZE;
3947 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003948 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003949 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003950 {
3951 if($ExtraDump)
3952 {
3953 if(not defined $TypeAttr{"Memb"}
3954 and not $Tmpl)
3955 { # declaration only
3956 $TypeAttr{"Forward"} = 1;
3957 }
3958 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003959 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003961 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003962 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003963 {
3964 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003965 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003966 }
3967 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003968 or $TypeAttr{"Type"} eq "Class")
3969 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003970 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003971 if($Skip) {
3972 return ();
3973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003974 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003975 if(my $Algn = getAlgn($TypeId)) {
3976 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003978 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003979
3980 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3981 {
3982 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003983 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003984 {
3985 if(not isAnon($TypeAttr{"Name"})) {
3986 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3987 }
3988 }
3989 }
3990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003991 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003992 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3993 {
3994 my @Entries = split(/\n/, $VTable);
3995 foreach (1 .. $#Entries)
3996 {
3997 my $Entry = $Entries[$_];
3998 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003999 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004000 }
4001 }
4002 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004003
4004 if($TypeAttr{"Type"} eq "Enum")
4005 {
4006 if(not $TypeAttr{"NameSpace"})
4007 {
4008 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4009 {
4010 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004011 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004012 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004013 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004014 "Header"=>$TypeAttr{"Header"}
4015 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004016 if(isAnon($TypeAttr{"Name"}))
4017 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004018 if($ExtraDump
4019 or is_target_header($TypeAttr{"Header"}, $Version))
4020 {
4021 %{$Constants{$Version}{$MName}} = (
4022 "Value" => $MVal,
4023 "Header" => $TypeAttr{"Header"}
4024 );
4025 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004026 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004027 }
4028 }
4029 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004030 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004031 {
4032 if(defined $TypedefToAnon{$TypeId}) {
4033 $TypeAttr{"AnonTypedef"} = 1;
4034 }
4035 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004037 return %TypeAttr;
4038}
4039
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004040sub simplifyVTable($)
4041{
4042 my $Content = $_[0];
4043 if($Content=~s/ \[with (.+)]//)
4044 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4045 if(my @Elems = separate_Params($1, 0, 0))
4046 {
4047 foreach my $Elem (@Elems)
4048 {
4049 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4050 {
4051 my ($Arg, $Val) = ($1, $2);
4052
4053 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4054 $Content=~s/,\s*$Arg\b//g;
4055 }
4056 else {
4057 $Content=~s/\b$Arg\b/$Val/g;
4058 }
4059 }
4060 }
4061 }
4062 }
4063
4064 return $Content;
4065}
4066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004067sub detect_lang($)
4068{
4069 my $TypeId = $_[0];
4070 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004071 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004072 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004073 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4074 }
4075 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004076 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004077 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004078 while($Fncs)
4079 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004080 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004081 return 1;
4082 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004083 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004084 }
4085 }
4086 return 0;
4087}
4088
4089sub setSpec($$)
4090{
4091 my ($TypeId, $TypeAttr) = @_;
4092 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4093 if($Info=~/\s+spec\s+/) {
4094 $TypeAttr->{"Spec"} = 1;
4095 }
4096}
4097
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004098sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004099{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004100 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004101 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004102 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004103 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004104 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004105 my $Pos = 0;
4106 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4107 {
4108 my ($Access, $BInfoId) = ($1, $2);
4109 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004110
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004111 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004112 { # class A<N>:public A<N-1>
4113 next;
4114 }
4115
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004116 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4117 if(not $CType or $CType eq "template_type_parm"
4118 or $CType eq "typename_type")
4119 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004120 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004122 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004123 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004124 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4125 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004126 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004127 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4128 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004129 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004131 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004132 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4133 }
4134 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004135 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004136 }
4137 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004138 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004139}
4140
4141sub getBinfClassId($)
4142{
4143 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004144 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4145 return $1;
4146 }
4147
4148 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004149}
4150
4151sub unmangledFormat($$)
4152{
4153 my ($Name, $LibVersion) = @_;
4154 $Name = uncover_typedefs($Name, $LibVersion);
4155 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4156 $Name=~s/\(\w+\)(\d)/$1/;
4157 return $Name;
4158}
4159
4160sub modelUnmangled($$)
4161{
4162 my ($InfoId, $Compiler) = @_;
4163 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4164 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4165 }
4166 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4167 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4168 $PureSignature = "~".$PureSignature;
4169 }
4170 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4171 {
4172 my (@Params, @ParamTypes) = ();
4173 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4174 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4175 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4176 }
4177 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4178 { # checking parameters
4179 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004180 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004181 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004182 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004183
4184 if($PName eq "this"
4185 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4186 {
4187 next;
4188 }
4189
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004190 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004191 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004192 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004193 }
4194 @ParamTypes = (@ParamTypes, $PTName);
4195 }
4196 if(@ParamTypes) {
4197 $PureSignature .= "(".join(", ", @ParamTypes).")";
4198 }
4199 else
4200 {
4201 if($Compiler eq "MSVC")
4202 {
4203 $PureSignature .= "(void)";
4204 }
4205 else
4206 { # GCC
4207 $PureSignature .= "()";
4208 }
4209 }
4210 $PureSignature = delete_keywords($PureSignature);
4211 }
4212 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004214 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004215 $PureSignature = $ClassName."::".$PureSignature;
4216 }
4217 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4218 $PureSignature = $NS."::".$PureSignature;
4219 }
4220 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4221 $PureSignature .= " const";
4222 }
4223 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4224 $PureSignature .= " volatile";
4225 }
4226 my $ShowReturn = 0;
4227 if($Compiler eq "MSVC"
4228 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4229 {
4230 $ShowReturn=1;
4231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004232 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4233 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004234 {
4235 $ShowReturn=1;
4236 }
4237 if($ShowReturn)
4238 { # mangled names for template function specializations include return value
4239 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4240 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004241 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004242 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4243 $PureSignature = $ReturnName." ".$PureSignature;
4244 }
4245 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004246 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004247}
4248
4249sub mangle_symbol($$$)
4250{ # mangling for simple methods
4251 # see gcc-4.6.0/gcc/cp/mangle.c
4252 my ($InfoId, $LibVersion, $Compiler) = @_;
4253 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4254 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4255 }
4256 my $Mangled = "";
4257 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004258 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004259 }
4260 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004261 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004262 }
4263 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4264}
4265
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004266sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004267{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004268 my ($InfoId, $LibVersion) = @_;
4269 return "";
4270}
4271
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004272sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004273{ # see gcc-4.6.0/gcc/cp/mangle.c
4274 my ($InfoId, $LibVersion) = @_;
4275 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004276 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004277 my %Repl = ();# SN_ replacements
4278 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4279 {
4280 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4281 if($MangledClass!~/\AN/) {
4282 $MangledClass = "N".$MangledClass;
4283 }
4284 else {
4285 $MangledClass=~s/E\Z//;
4286 }
4287 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4288 $MangledClass=~s/\AN/NV/;
4289 }
4290 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4291 $MangledClass=~s/\AN/NK/;
4292 }
4293 $Mangled .= $MangledClass;
4294 }
4295 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4296 { # mangled by name due to the absence of structured info
4297 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4298 if($MangledNS!~/\AN/) {
4299 $MangledNS = "N".$MangledNS;
4300 }
4301 else {
4302 $MangledNS=~s/E\Z//;
4303 }
4304 $Mangled .= $MangledNS;
4305 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004306 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004307 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004308 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004309 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004310 foreach (@TPos) {
4311 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4312 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004313 }
4314 elsif($TmplParams)
4315 { # remangling mode
4316 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004317 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004318 }
4319 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4320 $Mangled .= "C1";
4321 }
4322 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4323 $Mangled .= "D0";
4324 }
4325 elsif($ShortName)
4326 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004327 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4328 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004329 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004330 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004331 { # "const" global data is mangled as _ZL...
4332 $Mangled .= "L";
4333 }
4334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004335 if($ShortName=~/\Aoperator(\W.*)\Z/)
4336 {
4337 my $Op = $1;
4338 $Op=~s/\A[ ]+//g;
4339 if(my $OpMngl = $OperatorMangling{$Op}) {
4340 $Mangled .= $OpMngl;
4341 }
4342 else { # conversion operator
4343 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4344 }
4345 }
4346 else {
4347 $Mangled .= length($ShortName).$ShortName;
4348 }
4349 if(@TParams)
4350 { # templates
4351 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004352 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004353 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4354 }
4355 $Mangled .= "E";
4356 }
4357 if(not $ClassId and @TParams) {
4358 add_substitution($ShortName, \%Repl, 0);
4359 }
4360 }
4361 if($ClassId or $NameSpace) {
4362 $Mangled .= "E";
4363 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004364 if(@TParams)
4365 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004366 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004367 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4368 }
4369 }
4370 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4371 {
4372 my @Params = ();
4373 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4374 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4375 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4376 }
4377 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4378 { # checking parameters
4379 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4380 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4381 }
4382 if(not @Params) {
4383 $Mangled .= "v";
4384 }
4385 }
4386 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4387 $Mangled = write_stdcxx_substitution($Mangled);
4388 if($Mangled eq "_Z") {
4389 return "";
4390 }
4391 return $Mangled;
4392}
4393
4394sub correct_incharge($$$)
4395{
4396 my ($InfoId, $LibVersion, $Mangled) = @_;
4397 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4398 {
4399 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004400 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004401 }
4402 }
4403 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4404 {
4405 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004406 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004407 }
4408 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004409 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004410 }
4411 }
4412 return $Mangled;
4413}
4414
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004415sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004416{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004417 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004418 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004419 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004420 return $Name;
4421 }
4422 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004423 while(my $CPos = find_center($TParams, "<"))
4424 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004425 $TParams = substr($TParams, $CPos);
4426 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004427 if($TParams=~s/\A<(.+)>\Z/$1/) {
4428 $Name=~s/<\Q$TParams\E>\Z//;
4429 }
4430 else
4431 { # error
4432 $TParams = "";
4433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004434 return ($Name, $TParams);
4435}
4436
4437sub get_sub_ns($)
4438{
4439 my $Name = $_[0];
4440 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004441 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004442 {
4443 push(@NS, substr($Name, 0, $CPos));
4444 $Name = substr($Name, $CPos);
4445 $Name=~s/\A:://;
4446 }
4447 return (join("::", @NS), $Name);
4448}
4449
4450sub mangle_ns($$$)
4451{
4452 my ($Name, $LibVersion, $Repl) = @_;
4453 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4454 {
4455 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4456 $Mangled=~s/\AN(.+)E\Z/$1/;
4457 return $Mangled;
4458
4459 }
4460 else
4461 {
4462 my ($MangledNS, $SubNS) = ("", "");
4463 ($SubNS, $Name) = get_sub_ns($Name);
4464 if($SubNS) {
4465 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4466 }
4467 $MangledNS .= length($Name).$Name;
4468 add_substitution($MangledNS, $Repl, 0);
4469 return $MangledNS;
4470 }
4471}
4472
4473sub mangle_param($$$)
4474{
4475 my ($PTid, $LibVersion, $Repl) = @_;
4476 my ($MPrefix, $Mangled) = ("", "");
4477 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004478 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004479 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004480 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004481 if(not $BaseType_Name) {
4482 return "";
4483 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004484 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004485 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004486 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4487 while($Suffix=~/(&|\*|const)\Z/)
4488 {
4489 if($Suffix=~s/[ ]*&\Z//) {
4490 $MPrefix .= "R";
4491 }
4492 if($Suffix=~s/[ ]*\*\Z//) {
4493 $MPrefix .= "P";
4494 }
4495 if($Suffix=~s/[ ]*const\Z//)
4496 {
4497 if($MPrefix=~/R|P/
4498 or $Suffix=~/&|\*/) {
4499 $MPrefix .= "K";
4500 }
4501 }
4502 if($Suffix=~s/[ ]*volatile\Z//) {
4503 $MPrefix .= "V";
4504 }
4505 #if($Suffix=~s/[ ]*restrict\Z//) {
4506 #$MPrefix .= "r";
4507 #}
4508 }
4509 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4510 $Mangled .= $Token;
4511 }
4512 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4513 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004514 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004515 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004516 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004517 foreach (@TPos) {
4518 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4519 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004520 }
4521 elsif($TmplParams)
4522 { # remangling mode
4523 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004524 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004525 }
4526 my $MangledNS = "";
4527 my ($SubNS, $SName) = get_sub_ns($ShortName);
4528 if($SubNS) {
4529 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4530 }
4531 $MangledNS .= length($SName).$SName;
4532 if(@TParams) {
4533 add_substitution($MangledNS, $Repl, 0);
4534 }
4535 $Mangled .= "N".$MangledNS;
4536 if(@TParams)
4537 { # templates
4538 $Mangled .= "I";
4539 foreach my $TParam (@TParams) {
4540 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4541 }
4542 $Mangled .= "E";
4543 }
4544 $Mangled .= "E";
4545 }
4546 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4547 {
4548 if($BaseType{"Type"} eq "MethodPtr") {
4549 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4550 }
4551 else {
4552 $Mangled .= "PF";
4553 }
4554 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4555 my @Params = keys(%{$BaseType{"Param"}});
4556 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4557 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4558 }
4559 if(not @Params) {
4560 $Mangled .= "v";
4561 }
4562 $Mangled .= "E";
4563 }
4564 elsif($BaseType{"Type"} eq "FieldPtr")
4565 {
4566 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4567 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4568 }
4569 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4570 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4571 {
4572 if($Mangled eq $Optimized)
4573 {
4574 if($ShortName!~/::/)
4575 { # remove "N ... E"
4576 if($MPrefix) {
4577 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4578 }
4579 else {
4580 $Mangled=~s/\AN(.+)E\Z/$1/g;
4581 }
4582 }
4583 }
4584 else {
4585 $Mangled = $Optimized;
4586 }
4587 }
4588 add_substitution($Mangled, $Repl, 1);
4589 return $Mangled;
4590}
4591
4592sub mangle_template_param($$$)
4593{ # types + literals
4594 my ($TParam, $LibVersion, $Repl) = @_;
4595 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4596 return mangle_param($TPTid, $LibVersion, $Repl);
4597 }
4598 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4599 { # class_name<1u>::method(...)
4600 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4601 }
4602 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4603 { # class_name<(signed char)1>::method(...)
4604 return "L".$IntrinsicMangling{$1}.$2."E";
4605 }
4606 elsif($TParam eq "true")
4607 { # class_name<true>::method(...)
4608 return "Lb1E";
4609 }
4610 elsif($TParam eq "false")
4611 { # class_name<true>::method(...)
4612 return "Lb0E";
4613 }
4614 else { # internal error
4615 return length($TParam).$TParam;
4616 }
4617}
4618
4619sub add_substitution($$$)
4620{
4621 my ($Value, $Repl, $Rec) = @_;
4622 if($Rec)
4623 { # subtypes
4624 my @Subs = ($Value);
4625 while($Value=~s/\A(R|P|K)//) {
4626 push(@Subs, $Value);
4627 }
4628 foreach (reverse(@Subs)) {
4629 add_substitution($_, $Repl, 0);
4630 }
4631 return;
4632 }
4633 return if($Value=~/\AS(\d*)_\Z/);
4634 $Value=~s/\AN(.+)E\Z/$1/g;
4635 return if(defined $Repl->{$Value});
4636 return if(length($Value)<=1);
4637 return if($StdcxxMangling{$Value});
4638 # check for duplicates
4639 my $Base = $Value;
4640 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4641 {
4642 my $Num = $Repl->{$Type};
4643 my $Replace = macro_mangle($Num);
4644 $Base=~s/\Q$Replace\E/$Type/;
4645 }
4646 if(my $OldNum = $Repl->{$Base})
4647 {
4648 $Repl->{$Value} = $OldNum;
4649 return;
4650 }
4651 my @Repls = sort {$b<=>$a} values(%{$Repl});
4652 if(@Repls) {
4653 $Repl->{$Value} = $Repls[0]+1;
4654 }
4655 else {
4656 $Repl->{$Value} = -1;
4657 }
4658 # register duplicates
4659 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004660 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004661 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4662 {
4663 next if($Base eq $Type);
4664 my $Num = $Repl->{$Type};
4665 my $Replace = macro_mangle($Num);
4666 $Base=~s/\Q$Type\E/$Replace/;
4667 $Repl->{$Base} = $Repl->{$Value};
4668 }
4669}
4670
4671sub macro_mangle($)
4672{
4673 my $Num = $_[0];
4674 if($Num==-1) {
4675 return "S_";
4676 }
4677 else
4678 {
4679 my $Code = "";
4680 if($Num<10)
4681 { # S0_, S1_, S2_, ...
4682 $Code = $Num;
4683 }
4684 elsif($Num>=10 and $Num<=35)
4685 { # SA_, SB_, SC_, ...
4686 $Code = chr(55+$Num);
4687 }
4688 else
4689 { # S10_, S11_, S12_
4690 $Code = $Num-26; # 26 is length of english alphabet
4691 }
4692 return "S".$Code."_";
4693 }
4694}
4695
4696sub write_stdcxx_substitution($)
4697{
4698 my $Mangled = $_[0];
4699 if($StdcxxMangling{$Mangled}) {
4700 return $StdcxxMangling{$Mangled};
4701 }
4702 else
4703 {
4704 my @Repls = keys(%StdcxxMangling);
4705 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4706 foreach my $MangledType (@Repls)
4707 {
4708 my $Replace = $StdcxxMangling{$MangledType};
4709 #if($Mangled!~/$Replace/) {
4710 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4711 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4712 #}
4713 }
4714 }
4715 return $Mangled;
4716}
4717
4718sub write_substitution($$)
4719{
4720 my ($Mangled, $Repl) = @_;
4721 if(defined $Repl->{$Mangled}
4722 and my $MnglNum = $Repl->{$Mangled}) {
4723 $Mangled = macro_mangle($MnglNum);
4724 }
4725 else
4726 {
4727 my @Repls = keys(%{$Repl});
4728 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4729 # FIXME: how to apply replacements? by num or by pos
4730 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4731 foreach my $MangledType (@Repls)
4732 {
4733 my $Replace = macro_mangle($Repl->{$MangledType});
4734 if($Mangled!~/$Replace/) {
4735 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4736 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4737 }
4738 }
4739 }
4740 return $Mangled;
4741}
4742
4743sub delete_keywords($)
4744{
4745 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004746 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004747 return $TypeName;
4748}
4749
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004750sub uncover_typedefs($$)
4751{
4752 my ($TypeName, $LibVersion) = @_;
4753 return "" if(not $TypeName);
4754 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4755 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4756 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004757 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004758 while($TypeName_New ne $TypeName_Pre)
4759 {
4760 $TypeName_Pre = $TypeName_New;
4761 my $TypeName_Copy = $TypeName_New;
4762 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004763 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004764 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004765 if(not $Intrinsic_Keywords{$1}) {
4766 $Words{$1} = 1;
4767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004768 }
4769 foreach my $Word (keys(%Words))
4770 {
4771 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4772 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004773 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004774 if($BaseType_Name=~/\([\*]+\)/)
4775 { # FuncPtr
4776 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4777 {
4778 my $Type_Suffix = $1;
4779 $TypeName_New = $BaseType_Name;
4780 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004781 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004782 }
4783 }
4784 }
4785 else
4786 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004787 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004788 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004789 }
4790 }
4791 }
4792 }
4793 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4794}
4795
4796sub isInternal($)
4797{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004798 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4799 {
4800 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4801 {
4802 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4803 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4804 return 1;
4805 }
4806 }
4807 }
4808 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004809}
4810
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004811sub getDataVal($$)
4812{
4813 my ($InfoId, $TypeId) = @_;
4814 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4815 {
4816 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4817 {
4818 if(defined $LibInfo{$Version}{"info_type"}{$1}
4819 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004820 {
4821 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004822 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004823 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4824 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004825 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004826 if(my $Addr = getTreeAttr_Op($1)) {
4827 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004828 }
4829 }
4830 }
4831 }
4832 else {
4833 return getInitVal($1, $TypeId);
4834 }
4835 }
4836 }
4837 return undef;
4838}
4839
4840sub getInitVal($$)
4841{
4842 my ($InfoId, $TypeId) = @_;
4843 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4844 {
4845 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4846 {
4847 if($InfoType eq "integer_cst")
4848 {
4849 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004850 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004851 { # characters
4852 $Val = chr($Val);
4853 }
4854 return $Val;
4855 }
4856 elsif($InfoType eq "string_cst") {
4857 return getNodeStrCst($InfoId);
4858 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004859 elsif($InfoType eq "var_decl")
4860 {
4861 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4862 return $Name;
4863 }
4864 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004865 }
4866 }
4867 return undef;
4868}
4869
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004870sub set_Class_And_Namespace($)
4871{
4872 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004873 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004874 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004875 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004876 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004877 my $NSInfoId = $1;
4878 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4879 {
4880 if($InfoType eq "namespace_decl") {
4881 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4882 }
4883 elsif($InfoType eq "record_type") {
4884 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4885 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004887 }
4888 }
4889 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4890 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004891 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004892 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004893 { # skip
4894 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004896 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004897
4898 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004899}
4900
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004901sub debugMangling($)
4902{
4903 my $LibVersion = $_[0];
4904 my %Mangled = ();
4905 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4906 {
4907 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4908 {
4909 if($Mngl=~/\A(_Z|\?)/) {
4910 $Mangled{$Mngl}=$InfoId;
4911 }
4912 }
4913 }
4914 translateSymbols(keys(%Mangled), $LibVersion);
4915 foreach my $Mngl (keys(%Mangled))
4916 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004917 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4918 my $U2 = $tr_name{$Mngl};
4919 if($U1 ne $U2) {
4920 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004921 }
4922 }
4923}
4924
4925sub linkSymbol($)
4926{ # link symbols from shared libraries
4927 # with the symbols from header files
4928 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004929 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004930 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004931 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4932 or $EMERGENCY_MODE_48)
4933 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4934 # 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 +03004935 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004936 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004937 {
4938 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4939 return correct_incharge($InfoId, $Version, $Mangled);
4940 }
4941 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004942 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004943 or not $BinaryOnly
4944 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004945 { # 1. --headers-only mode
4946 # 2. not mangled src-only symbols
4947 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4948 return $Mangled;
4949 }
4950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004951 }
4952 return "";
4953}
4954
4955sub setLanguage($$)
4956{
4957 my ($LibVersion, $Lang) = @_;
4958 if(not $UserLang) {
4959 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4960 }
4961}
4962
4963sub getSymbolInfo($)
4964{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004965 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004966 if(isInternal($InfoId)) {
4967 return;
4968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004969 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4970 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004971 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4972 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004973 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004974 return;
4975 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004976 setFuncAccess($InfoId);
4977 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004978 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4979 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004980 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004981 return;
4982 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004983
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004984 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004985 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004986 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004987 if(not defined $TypeInfo{$Version}{$Return}
4988 or not $TypeInfo{$Version}{$Return}{"Name"})
4989 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004990 delete($SymbolInfo{$Version}{$InfoId});
4991 return;
4992 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004993 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004994 }
4995 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4996 {
4997 if(defined $MissedTypedef{$Version}{$Rid})
4998 {
4999 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5000 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5001 }
5002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005003 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005004 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5005 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005006 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005007 my $Orig = getFuncOrig($InfoId);
5008 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005009 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5010 {
5011 delete($SymbolInfo{$Version}{$InfoId});
5012 return;
5013 }
5014
5015 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005016 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005017 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005018 return;
5019 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005020
5021 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005022 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005023 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5024
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005025 my @TParams = getTParams($Orig, "Func");
5026 if(not @TParams)
5027 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005028 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005029 return;
5030 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005031 foreach my $Pos (0 .. $#TParams)
5032 {
5033 my $Val = $TParams[$Pos];
5034 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5035
5036 if($Tmpl)
5037 {
5038 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5039 {
5040 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5041 }
5042 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005043 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005044
5045 if($Tmpl)
5046 {
5047 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5048 {
5049 if($Pos>$#TParams)
5050 {
5051 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5052 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5053 }
5054 }
5055 }
5056
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005057 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5058 { # operator<< <T>, operator>> <T>
5059 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5060 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005061 if(@TParams) {
5062 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5063 }
5064 else {
5065 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5066 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005067 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005068 }
5069 else
5070 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005071 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005072 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005073 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5074 {
5075 if($OSgroup eq "windows")
5076 { # cut the offset
5077 $MnglName=~s/\@\d+\Z//g;
5078 }
5079 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5080
5081 # NOTE: mangling of some symbols may change depending on GCC version
5082 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5083 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5084 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005085
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005086 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005087 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005088 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005089 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005090 return;
5091 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005092 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005093 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005094 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005095 if($Skip)
5096 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005097 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005098 return;
5099 }
5100 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005101 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5102 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5103 }
5104
5105 if(set_Class_And_Namespace($InfoId))
5106 {
5107 delete($SymbolInfo{$Version}{$InfoId});
5108 return;
5109 }
5110
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005111 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5112 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005113 if(not defined $TypeInfo{$Version}{$ClassId}
5114 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5115 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005116 delete($SymbolInfo{$Version}{$InfoId});
5117 return;
5118 }
5119 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005120 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5121 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005122 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005123 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005124 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005125 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005126 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005127 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 }
5129 if($COMMON_LANGUAGE{$Version} eq "C++")
5130 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005131 # C++ or --headers-only mode
5132 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005133 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005134 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5135 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005136 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005137 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005138 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005139 if(my $Mangled = linkSymbol($InfoId)) {
5140 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005141 }
5142 }
5143 if($OStarget eq "windows")
5144 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005145 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005147 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005148 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005149 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005150 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005151 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005152 }
5153 }
5154 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005155 else
5156 { # not mangled in C
5157 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5158 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005159 if(not $CheckHeadersOnly
5160 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5161 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5162 {
5163 my $Incorrect = 0;
5164
5165 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5166 {
5167 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5168 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5169 { # mangled in the TU dump, but not mangled in the library
5170 $Incorrect = 1;
5171 }
5172 }
5173 else
5174 {
5175 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5176 { # all C++ functions are not mangled in the TU dump
5177 $Incorrect = 1;
5178 }
5179 }
5180 if($Incorrect)
5181 {
5182 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5183 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5184 }
5185 }
5186 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005187 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005188 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005189 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005190 return;
5191 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005192 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005193 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005194 { # identify virtual and pure virtual functions
5195 # NOTE: constructors cannot be virtual
5196 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5197 # in the TU dump, so taking it from the original symbol
5198 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5199 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5200 { # NOTE: D2 destructors are not present in a v-table
5201 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005203 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005204 if(isInline($InfoId)) {
5205 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005206 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005207 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005208 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5209 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005210 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5211 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005212 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005213 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005214 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005215 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005216 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005217 }
5218 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005219 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5220 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005221 if(not $ExtraDump)
5222 {
5223 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5224 { # non-target symbols
5225 delete($SymbolInfo{$Version}{$InfoId});
5226 return;
5227 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005229 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005230 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5231 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5232 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5233 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005235 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5236 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005237 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005238 return;
5239 }
5240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005241 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005242 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 return;
5247 }
5248 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005249 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 }
5251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005252 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5253 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5254 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5257 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005258 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005259 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005260 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005261 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005262 }
5263 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005264 if(getFuncLink($InfoId) eq "Static") {
5265 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005266 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005267 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5268 {
5269 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5270 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005271 if($Unmangled=~/\.\_\d/)
5272 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005273 delete($SymbolInfo{$Version}{$InfoId});
5274 return;
5275 }
5276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005277 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005278
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005279 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5280 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005282 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5283 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005284 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005285
5286 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5287 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5288 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005289
5290 if($ExtraDump) {
5291 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5292 }
5293}
5294
5295sub guessHeader($)
5296{
5297 my $InfoId = $_[0];
5298 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5299 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5300 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5301 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5302 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5303 {
5304 if(get_filename($HPath) eq $Header)
5305 {
5306 my $HDir = get_filename(get_dirname($HPath));
5307 if($HDir ne "include"
5308 and $HDir=~/\A[a-z]+\Z/i) {
5309 return join_P($HDir, $Header);
5310 }
5311 }
5312 }
5313 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005314}
5315
5316sub isInline($)
5317{ # "body: undefined" in the tree
5318 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005319 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5320 {
5321 if($Info=~/ undefined /i) {
5322 return 0;
5323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005324 }
5325 return 1;
5326}
5327
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005328sub hasThrow($)
5329{
5330 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5331 {
5332 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5333 return getTreeAttr_Unql($1, "unql");
5334 }
5335 }
5336 return 1;
5337}
5338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005339sub getTypeId($)
5340{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005341 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5342 {
5343 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5344 return $1;
5345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005346 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005347 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005348}
5349
5350sub setTypeMemb($$)
5351{
5352 my ($TypeId, $TypeAttr) = @_;
5353 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005354 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005355 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005356 if($TypeType eq "Enum")
5357 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005358 my $MInfoId = getTreeAttr_Csts($TypeId);
5359 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005360 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005361 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5362 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005363 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005364 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5365 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005366 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005367 }
5368 }
5369 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5370 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005371 my $MInfoId = getTreeAttr_Flds($TypeId);
5372 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005373 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005374 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5375 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005376 if(not $IType or $IType ne "field_decl")
5377 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005378
5379 if($IType eq "var_decl")
5380 { # static field
5381 $StaticFields = 1;
5382 }
5383
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005384 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005385 next;
5386 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005387 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005388 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005389 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005390 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005391 }
5392 if(not $StructMembName)
5393 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005394 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005396 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005397 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5398 if(isAnon($UnnamedTName))
5399 { # rename unnamed fields to unnamed0, unnamed1, ...
5400 $StructMembName = "unnamed".($UnnamedPos++);
5401 }
5402 }
5403 }
5404 if(not $StructMembName)
5405 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005406 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005407 next;
5408 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005409 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005410 if(defined $MissedTypedef{$Version}{$MembTypeId})
5411 {
5412 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5413 $MembTypeId = $AddedTid;
5414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005415 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005416
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005417 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5418 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005419 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005420 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005421 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5422 }
5423 if($MInfo=~/spec:\s*mutable /)
5424 { # mutable fields
5425 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005426 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005427 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005428 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5429 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005430 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005431 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005432 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005433 }
5434 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005435 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005436 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5437 { # template
5438 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5439 }
5440 else {
5441 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005444
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005445 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005446 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 }
5448 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005449
5450 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005451}
5452
5453sub setFuncParams($)
5454{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005455 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005456 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005457
5458 my $FType = getFuncType($InfoId);
5459
5460 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005461 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005462 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5463 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005464 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005465 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005466 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5467 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005468 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005469 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005472 else
5473 { # skip
5474 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005475 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005476 # skip "this"-parameter
5477 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005478 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005479 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005481 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005482 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5483 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5484 if(not $ParamName)
5485 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005486 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005487 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005488 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5489 {
5490 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5491 $ParamTypeId = $AddedTid;
5492 }
5493 }
5494 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495 if(not $PType or $PType eq "Unknown") {
5496 return 1;
5497 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005498 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005499 if(not $PTName) {
5500 return 1;
5501 }
5502 if($PTName eq "void") {
5503 last;
5504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005505 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005506 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005507 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005508 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005509 $ParamInfoId = getNextElem($ParamInfoId);
5510 next;
5511 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005512 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005513
5514 if(my %Base = get_BaseType($ParamTypeId, $Version))
5515 {
5516 if(defined $Base{"Template"}) {
5517 return 1;
5518 }
5519 }
5520
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005521 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005522 if(my $Algn = getAlgn($ParamInfoId)) {
5523 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5526 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005527 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005528 }
5529 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005530 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005531 if($ParamName ne "this" or $FType ne "Method") {
5532 $PPos += 1;
5533 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005534 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005535 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005536 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005537 }
5538 return 0;
5539}
5540
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005541sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005542{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005543 my ($InfoId, $Vtt_Pos) = @_;
5544 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005545 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005546 my $FType = getFuncType($InfoId);
5547
5548 if($FType eq "Method")
5549 {
5550 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005551 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005552 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005553 if(not $ParamListElemId)
5554 { # foo(...)
5555 return 1;
5556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005557 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005558 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005560 { # actual params: may differ from formal args
5561 # formal int*const
5562 # actual: int*
5563 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005564 {
5565 $Vtt_Pos=-1;
5566 $ParamListElemId = getNextElem($ParamListElemId);
5567 next;
5568 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005569 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5570 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005571 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005572 $HaveVoid = 1;
5573 last;
5574 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005575 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005576 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005577 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5578 {
5579 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5580 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5581 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005582 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005583 }
5584 }
5585 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5586 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005587 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005588 { # params
5589 if($OldId ne $ParamTypeId)
5590 {
5591 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5592 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5593
5594 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5595 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5596 }
5597 }
5598 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005599 }
5600 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005601 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005602 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005603 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5604 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005605 if($PurpType eq "nop_expr")
5606 { # func ( const char* arg = (const char*)(void*)0 )
5607 $PurpId = getTreeAttr_Op($PurpId);
5608 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005609 my $Val = getInitVal($PurpId, $ParamTypeId);
5610 if(defined $Val) {
5611 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5612 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005613 }
5614 }
5615 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005616 if($Pos!=0 or $FType ne "Method") {
5617 $PPos += 1;
5618 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005619 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005620 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005621 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005622}
5623
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005624sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005625{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005626 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5627 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005628 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5629 return $1;
5630 }
5631 }
5632 return "";
5633}
5634
5635sub getTreeAttr_Chain($)
5636{
5637 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5638 {
5639 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5640 return $1;
5641 }
5642 }
5643 return "";
5644}
5645
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005646sub getTreeAttr_Unql($)
5647{
5648 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5649 {
5650 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5651 return $1;
5652 }
5653 }
5654 return "";
5655}
5656
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005657sub getTreeAttr_Scpe($)
5658{
5659 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5660 {
5661 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5662 return $1;
5663 }
5664 }
5665 return "";
5666}
5667
5668sub getTreeAttr_Type($)
5669{
5670 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5671 {
5672 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5673 return $1;
5674 }
5675 }
5676 return "";
5677}
5678
5679sub getTreeAttr_Name($)
5680{
5681 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5682 {
5683 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5684 return $1;
5685 }
5686 }
5687 return "";
5688}
5689
5690sub getTreeAttr_Mngl($)
5691{
5692 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5693 {
5694 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5695 return $1;
5696 }
5697 }
5698 return "";
5699}
5700
5701sub getTreeAttr_Prms($)
5702{
5703 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5704 {
5705 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5706 return $1;
5707 }
5708 }
5709 return "";
5710}
5711
5712sub getTreeAttr_Fncs($)
5713{
5714 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5715 {
5716 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5717 return $1;
5718 }
5719 }
5720 return "";
5721}
5722
5723sub getTreeAttr_Csts($)
5724{
5725 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5726 {
5727 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5728 return $1;
5729 }
5730 }
5731 return "";
5732}
5733
5734sub getTreeAttr_Purp($)
5735{
5736 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5737 {
5738 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5739 return $1;
5740 }
5741 }
5742 return "";
5743}
5744
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005745sub getTreeAttr_Op($)
5746{
5747 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5748 {
5749 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5750 return $1;
5751 }
5752 }
5753 return "";
5754}
5755
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005756sub getTreeAttr_Valu($)
5757{
5758 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5759 {
5760 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5761 return $1;
5762 }
5763 }
5764 return "";
5765}
5766
5767sub getTreeAttr_Flds($)
5768{
5769 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5770 {
5771 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5772 return $1;
5773 }
5774 }
5775 return "";
5776}
5777
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005778sub getTreeAttr_Binf($)
5779{
5780 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5781 {
5782 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5783 return $1;
5784 }
5785 }
5786 return "";
5787}
5788
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005789sub getTreeAttr_Args($)
5790{
5791 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5792 {
5793 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005794 return $1;
5795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005796 }
5797 return "";
5798}
5799
5800sub getTreeValue($)
5801{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005802 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5803 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005804 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5805 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005807 }
5808 return "";
5809}
5810
5811sub getTreeAccess($)
5812{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005813 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005814 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005815 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5816 {
5817 my $Access = $1;
5818 if($Access eq "prot") {
5819 return "protected";
5820 }
5821 elsif($Access eq "priv") {
5822 return "private";
5823 }
5824 }
5825 elsif($Info=~/ protected /)
5826 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005827 return "protected";
5828 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005829 elsif($Info=~/ private /)
5830 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005831 return "private";
5832 }
5833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005834 return "public";
5835}
5836
5837sub setFuncAccess($)
5838{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005839 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005840 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005841 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005842 }
5843 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005844 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005845 }
5846}
5847
5848sub setTypeAccess($$)
5849{
5850 my ($TypeId, $TypeAttr) = @_;
5851 my $Access = getTreeAccess($TypeId);
5852 if($Access eq "protected") {
5853 $TypeAttr->{"Protected"} = 1;
5854 }
5855 elsif($Access eq "private") {
5856 $TypeAttr->{"Private"} = 1;
5857 }
5858}
5859
5860sub setFuncKind($)
5861{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005862 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5863 {
5864 if($Info=~/pseudo tmpl/) {
5865 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5866 }
5867 elsif($Info=~/ constructor /) {
5868 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5869 }
5870 elsif($Info=~/ destructor /) {
5871 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005873 }
5874}
5875
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005876sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005877{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005878 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5879 {
5880 if($Info=~/spec[ ]*:[ ]*pure /) {
5881 return "PureVirt";
5882 }
5883 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5884 return "Virt";
5885 }
5886 elsif($Info=~/ pure\s+virtual /)
5887 { # support for old GCC versions
5888 return "PureVirt";
5889 }
5890 elsif($Info=~/ virtual /)
5891 { # support for old GCC versions
5892 return "Virt";
5893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005894 }
5895 return "";
5896}
5897
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005898sub getFuncLink($)
5899{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005900 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5901 {
5902 if($Info=~/link[ ]*:[ ]*static /) {
5903 return "Static";
5904 }
5905 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005906 return $1;
5907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005908 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005909 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005910}
5911
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005912sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005914 my ($Symbol, $LibVersion) = @_;
5915 return "" if(not $Symbol or not $LibVersion);
5916 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5917 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005918 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005919 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5920 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5921 }
5922 }
5923 if($NS)
5924 {
5925 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5926 return $NS;
5927 }
5928 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005930 while($NS=~s/::[^:]+\Z//)
5931 {
5932 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5933 return $NS;
5934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005935 }
5936 }
5937 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005938
5939 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005940}
5941
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005942sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005943{
5944 my ($TypeName, $LibVersion) = @_;
5945 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005946 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005947 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005948 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5949 return $NS;
5950 }
5951 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005952 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005953 while($NS=~s/::[^:]+\Z//)
5954 {
5955 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5956 return $NS;
5957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005958 }
5959 }
5960 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005961 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962}
5963
5964sub getNameSpace($)
5965{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005966 my $InfoId = $_[0];
5967 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005968 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005969 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005970 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005971 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005972 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005973 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5974 {
5975 my $NameSpace = getTreeStr($1);
5976 if($NameSpace eq "::")
5977 { # global namespace
5978 return "";
5979 }
5980 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5981 $NameSpace = $BaseNameSpace."::".$NameSpace;
5982 }
5983 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5984 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005985 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005986 else {
5987 return "";
5988 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005989 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005990 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005991 { # inside data type
5992 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5993 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005997 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005998}
5999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006000sub getEnumMembVal($)
6001{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006002 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006004 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6005 {
6006 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6007 {
6008 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6009 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6010 return getTreeValue($1);
6011 }
6012 else
6013 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6014 return getTreeValue($1);
6015 }
6016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006017 }
6018 }
6019 return "";
6020}
6021
6022sub getSize($)
6023{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006024 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6025 {
6026 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6027 return getTreeValue($1);
6028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006031}
6032
6033sub getAlgn($)
6034{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006035 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6036 {
6037 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6038 return $1;
6039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006040 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006041 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006042}
6043
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006044sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006045{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006046 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6047 {
6048 if($Info=~/ bitfield /) {
6049 return getSize($_[0]);
6050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006052 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006053}
6054
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006055sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006056{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006057 if(my $Chan = getTreeAttr_Chan($_[0])) {
6058 return $Chan;
6059 }
6060 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6061 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006063 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006064}
6065
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006066sub registerHeader($$)
6067{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006069 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006070 return "";
6071 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006072 if(is_abs($Header) and not -f $Header)
6073 { # incorrect absolute path
6074 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006075 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006076 if(skipHeader($Header, $LibVersion))
6077 { # skip
6078 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006080 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6081 {
6082 detect_header_includes($Header_Path, $LibVersion);
6083
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006084 if(defined $Tolerance and $Tolerance=~/3/)
6085 { # 3 - skip headers that include non-Linux headers
6086 if($OSgroup ne "windows")
6087 {
6088 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6089 {
6090 if(specificHeader($Inc, "windows")) {
6091 return "";
6092 }
6093 }
6094 }
6095 }
6096
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006097 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6098 { # redirect
6099 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6100 or skipHeader($RHeader_Path, $LibVersion))
6101 { # skip
6102 return "";
6103 }
6104 $Header_Path = $RHeader_Path;
6105 }
6106 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6107 { # skip
6108 return "";
6109 }
6110
6111 if(my $HName = get_filename($Header_Path))
6112 { # register
6113 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6114 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6115 }
6116
6117 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6118 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006119 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006120 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006121 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006122 }
6123
6124 if($CheckHeadersOnly
6125 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6126 { # /usr/include/c++/4.6.1/...
6127 $STDCXX_TESTING = 1;
6128 }
6129
6130 return $Header_Path;
6131 }
6132 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006133}
6134
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006135sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006136{
6137 my ($Dir, $WithDeps, $LibVersion) = @_;
6138 $Dir=~s/[\/\\]+\Z//g;
6139 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006140 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006141
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006142 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006143 if($WithDeps)
6144 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006145 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6146 return;
6147 }
6148 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6149 $Mode = "DepsOnly";
6150 }
6151 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006152 else
6153 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006154 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6155 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6156 return;
6157 }
6158 }
6159 $Header_Dependency{$LibVersion}{$Dir} = 1;
6160 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6161 if($Mode eq "DepsOnly")
6162 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006163 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164 $Header_Dependency{$LibVersion}{$Path} = 1;
6165 }
6166 return;
6167 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006168 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006169 {
6170 if($WithDeps)
6171 {
6172 my $SubDir = $Path;
6173 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6174 { # register all sub directories
6175 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6176 }
6177 }
6178 next if(is_not_header($Path));
6179 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006180 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006181 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006182 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6183 }
6184 }
6185 if(get_filename($Dir) eq "include")
6186 { # search for "lib/include/" directory
6187 my $LibDir = $Dir;
6188 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006189 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006190 }
6191 }
6192}
6193
6194sub parse_redirect($$$)
6195{
6196 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197 my @Errors = ();
6198 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6199 push(@Errors, $1);
6200 }
6201 my $Redirect = "";
6202 foreach (@Errors)
6203 {
6204 s/\s{2,}/ /g;
6205 if(/(only|must\ include
6206 |update\ to\ include
6207 |replaced\ with
6208 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006209 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006210 {
6211 $Redirect = $2;
6212 last;
6213 }
6214 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6215 {
6216 $Redirect = $2;
6217 last;
6218 }
6219 elsif(/this\ header\ should\ not\ be\ used
6220 |programs\ should\ not\ directly\ include
6221 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6222 |is\ not\ supported\ API\ for\ general\ use
6223 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006224 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006225 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6226 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6227 }
6228 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006229 if($Redirect)
6230 {
6231 $Redirect=~s/\A<//g;
6232 $Redirect=~s/>\Z//g;
6233 }
6234 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006235}
6236
6237sub parse_includes($$)
6238{
6239 my ($Content, $Path) = @_;
6240 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006241 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006242 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006243 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006244 my $Method = substr($Header, 0, 1, "");
6245 substr($Header, length($Header)-1, 1, "");
6246 $Header = path_format($Header, $OSgroup);
6247 if($Method eq "\"" or is_abs($Header))
6248 {
6249 if(-e join_P(get_dirname($Path), $Header))
6250 { # relative path exists
6251 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006252 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006253 else
6254 { # include "..." that doesn't exist is equal to include <...>
6255 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006257 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006258 else {
6259 $Includes{$Header} = 1;
6260 }
6261 }
6262 if($ExtraInfo)
6263 {
6264 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6265 { # FT_FREETYPE_H
6266 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006267 }
6268 }
6269 return \%Includes;
6270}
6271
6272sub ignore_path($)
6273{
6274 my $Path = $_[0];
6275 if($Path=~/\~\Z/)
6276 {# skipping system backup files
6277 return 1;
6278 }
6279 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6280 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6281 return 1;
6282 }
6283 return 0;
6284}
6285
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006286sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006287{
6288 my ($ArrRef, $W) = @_;
6289 return if(length($W)<2);
6290 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6291}
6292
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006293sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006294{
6295 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006296
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006297 $H1=~s/\.[a-z]+\Z//ig;
6298 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006299
6300 my $Hname1 = get_filename($H1);
6301 my $Hname2 = get_filename($H2);
6302 my $HDir1 = get_dirname($H1);
6303 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006304 my $Dirname1 = get_filename($HDir1);
6305 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006306
6307 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6308 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6309
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006310 if($_[0] eq $_[1]
6311 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006312 return 0;
6313 }
6314 elsif($H1=~/\A\Q$H2\E/) {
6315 return 1;
6316 }
6317 elsif($H2=~/\A\Q$H1\E/) {
6318 return -1;
6319 }
6320 elsif($HDir1=~/\Q$Hname1\E/i
6321 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006322 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006323 return -1;
6324 }
6325 elsif($HDir2=~/\Q$Hname2\E/i
6326 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006327 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006328 return 1;
6329 }
6330 elsif($Hname1=~/\Q$Dirname1\E/i
6331 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006332 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006333 return -1;
6334 }
6335 elsif($Hname2=~/\Q$Dirname2\E/i
6336 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006337 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 return 1;
6339 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006340 elsif($Hname1=~/(config|lib|util)/i
6341 and $Hname2!~/(config|lib|util)/i)
6342 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 return -1;
6344 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006345 elsif($Hname2=~/(config|lib|util)/i
6346 and $Hname1!~/(config|lib|util)/i)
6347 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006348 return 1;
6349 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006350 else
6351 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006352 my $R1 = checkRelevance($H1);
6353 my $R2 = checkRelevance($H2);
6354 if($R1 and not $R2)
6355 { # libebook/e-book.h
6356 return -1;
6357 }
6358 elsif($R2 and not $R1)
6359 { # libebook/e-book.h
6360 return 1;
6361 }
6362 else
6363 {
6364 return (lc($H1) cmp lc($H2));
6365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006366 }
6367}
6368
6369sub searchForHeaders($)
6370{
6371 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006373 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006374 registerGccHeaders();
6375
6376 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6377 { # c++ standard include paths
6378 registerCppHeaders();
6379 }
6380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006381 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006382 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6383 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006384 {
6385 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006386 if($SystemRoot)
6387 {
6388 if(is_abs($Path)) {
6389 $Path = $SystemRoot.$Path;
6390 }
6391 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006392 if(not -e $Path) {
6393 exitStatus("Access_Error", "can't access \'$Path\'");
6394 }
6395 elsif(-f $Path) {
6396 exitStatus("Access_Error", "\'$Path\' - not a directory");
6397 }
6398 elsif(-d $Path)
6399 {
6400 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006401 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006402 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6403 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006404 }
6405 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006406 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006407 }
6408 }
6409 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006410 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006411 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6412 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006413
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006414 # registering directories
6415 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6416 {
6417 next if(not -e $Path);
6418 $Path = get_abs_path($Path);
6419 $Path = path_format($Path, $OSgroup);
6420 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006421 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 }
6423 elsif(-f $Path)
6424 {
6425 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006426 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006427 and not $LocalIncludes{$Dir})
6428 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006429 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006430 # if(my $OutDir = get_dirname($Dir))
6431 # { # registering the outer directory
6432 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6433 # and not $LocalIncludes{$OutDir}) {
6434 # registerDir($OutDir, 0, $LibVersion);
6435 # }
6436 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 }
6438 }
6439 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006440
6441 # clean memory
6442 %RegisteredDirs = ();
6443
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006444 # registering headers
6445 my $Position = 0;
6446 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6447 {
6448 if(is_abs($Dest) and not -e $Dest) {
6449 exitStatus("Access_Error", "can't access \'$Dest\'");
6450 }
6451 $Dest = path_format($Dest, $OSgroup);
6452 if(is_header($Dest, 1, $LibVersion))
6453 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006454 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006455 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6456 }
6457 }
6458 elsif(-d $Dest)
6459 {
6460 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006461 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006462 {
6463 next if(ignore_path($Path));
6464 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006465 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006466 push(@Registered, $HPath);
6467 }
6468 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006469 @Registered = sort {sortHeaders($a, $b)} @Registered;
6470 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006471 foreach my $Path (@Registered) {
6472 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6473 }
6474 }
6475 else {
6476 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6477 }
6478 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006479
6480 if(defined $Tolerance and $Tolerance=~/4/)
6481 { # 4 - skip headers included by others
6482 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6483 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006484 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006485 delete($Registered_Headers{$LibVersion}{$Path});
6486 }
6487 }
6488 }
6489
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006490 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6491 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006492 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006493 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006494 if(is_abs($Header) and not -f $Header) {
6495 exitStatus("Access_Error", "can't access file \'$Header\'");
6496 }
6497 $Header = path_format($Header, $OSgroup);
6498 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6499 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006500 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006501 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006502 }
6503 else {
6504 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006506 }
6507 }
6508 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6509 { # set relative paths (for duplicates)
6510 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6511 { # search for duplicates
6512 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6513 my $Prefix = get_dirname($FirstPath);
6514 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6515 { # detect a shortest distinguishing prefix
6516 my $NewPrefix = $1;
6517 my %Identity = ();
6518 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6519 {
6520 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6521 $Identity{$Path} = $1;
6522 }
6523 }
6524 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006525 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006526 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6527 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6528 }
6529 last;
6530 }
6531 $Prefix = $NewPrefix; # increase prefix
6532 }
6533 }
6534 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006535
6536 # clean memory
6537 %HeaderName_Paths = ();
6538
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006539 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6540 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006541 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006542 my ($Pos, $PairPos) = (-1, -1);
6543 my ($Path, $PairPath) = ();
6544 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6545 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6546 foreach my $Header_Path (@Paths)
6547 {
6548 if(get_filename($Header_Path) eq $PairName)
6549 {
6550 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6551 $PairPath = $Header_Path;
6552 }
6553 if(get_filename($Header_Path) eq $HeaderName)
6554 {
6555 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6556 $Path = $Header_Path;
6557 }
6558 }
6559 if($PairPos!=-1 and $Pos!=-1
6560 and int($PairPos)<int($Pos))
6561 {
6562 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6563 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6564 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6565 }
6566 }
6567 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6568 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6569 }
6570}
6571
6572sub detect_real_includes($$)
6573{
6574 my ($AbsPath, $LibVersion) = @_;
6575 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6576 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6577 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6578 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6579 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006580 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6581
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006582 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6583 return () if(not $Path);
6584 open(PREPROC, $Path);
6585 while(<PREPROC>)
6586 {
6587 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6588 {
6589 my $Include = path_format($1, $OSgroup);
6590 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6591 next;
6592 }
6593 if($Include eq $AbsPath) {
6594 next;
6595 }
6596 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6597 }
6598 }
6599 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006600 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6601}
6602
6603sub detect_header_includes($$)
6604{
6605 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006606 return if(not $LibVersion or not $Path);
6607 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6608 return;
6609 }
6610 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6611
6612 if(not -e $Path) {
6613 return;
6614 }
6615
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006616 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006617 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6618 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006619 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006620 {
6621 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006622 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006623 }
6624 if($RedirectPath ne $Path) {
6625 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6626 }
6627 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006628 else
6629 { # can't find
6630 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006632 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006633 if(my $Inc = parse_includes($Content, $Path))
6634 {
6635 foreach my $Include (keys(%{$Inc}))
6636 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006637 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006638
6639 if(defined $Tolerance and $Tolerance=~/4/)
6640 {
6641 if(my $HPath = identifyHeader($Include, $LibVersion))
6642 {
6643 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6644 }
6645 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006648}
6649
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006650sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006651{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006652 my $Path = $_[0];
6653 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006654 if($OStarget eq "symbian")
6655 {
6656 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6657 { # epoc32/include/libc/{stdio, ...}.h
6658 return 1;
6659 }
6660 }
6661 else
6662 {
6663 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6664 { # /usr/include/{stdio, ...}.h
6665 return 1;
6666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006668 return 0;
6669}
6670
6671sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006672{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006673 my $Dir = $_[0];
6674 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006675 if($OStarget eq "symbian")
6676 {
6677 if(get_filename($OutDir) eq "libc"
6678 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6679 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6680 return 1;
6681 }
6682 }
6683 else
6684 { # linux
6685 if($OutDir eq "/usr/include"
6686 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6687 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6688 return 1;
6689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006690 }
6691 return 0;
6692}
6693
6694sub detect_recursive_includes($$)
6695{
6696 my ($AbsPath, $LibVersion) = @_;
6697 return () if(not $AbsPath);
6698 if(isCyclical(\@RecurInclude, $AbsPath)) {
6699 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6700 }
6701 my ($AbsDir, $Name) = separate_path($AbsPath);
6702 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006703 { # system GLIBC internals
6704 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006705 }
6706 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6707 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6708 }
6709 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006710
6711 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6712 { # skip /usr/include/c++/*/ headers
6713 return () if(not $ExtraInfo);
6714 }
6715
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006716 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006717 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006718 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006719 { # check "real" (non-"model") include paths
6720 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6721 pop(@RecurInclude);
6722 return @Paths;
6723 }
6724 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6725 detect_header_includes($AbsPath, $LibVersion);
6726 }
6727 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6728 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006729 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006730 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006731 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006732 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006733 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006734 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006735 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006736 }
6737 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006738 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006739 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006740 { # search for the nearest header
6741 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006742 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006743 if(-f $Candidate) {
6744 $HPath = $Candidate;
6745 }
6746 }
6747 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006748 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006749 }
6750 next if(not $HPath);
6751 if($HPath eq $AbsPath) {
6752 next;
6753 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006754
6755 if($Debug)
6756 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006757# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6758# {
6759# print STDERR "$AbsPath -> $HPath\n";
6760# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006761 }
6762
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006763 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6764 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006765 { # only include <...>, skip include "..." prefixes
6766 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6767 }
6768 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6769 {
6770 if($IncPath eq $AbsPath) {
6771 next;
6772 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006773 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6774 if($RIncType==-1)
6775 { # include "..."
6776 $RIncType = $IncType;
6777 }
6778 elsif($RIncType==2)
6779 {
6780 if($IncType!=-1) {
6781 $RIncType = $IncType;
6782 }
6783 }
6784 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006785 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6786 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6787 }
6788 }
6789 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6790 {
6791 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6792 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6793 { # distinguish math.h from glibc and math.h from the tested library
6794 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6795 last;
6796 }
6797 }
6798 }
6799 pop(@RecurInclude);
6800 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6801}
6802
6803sub find_in_framework($$$)
6804{
6805 my ($Header, $Framework, $LibVersion) = @_;
6806 return "" if(not $Header or not $Framework or not $LibVersion);
6807 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6808 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6809 }
6810 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6811 {
6812 if(get_filename($Dependency) eq $Framework
6813 and -f get_dirname($Dependency)."/".$Header) {
6814 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6815 }
6816 }
6817 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6818}
6819
6820sub find_in_defaults($)
6821{
6822 my $Header = $_[0];
6823 return "" if(not $Header);
6824 if(defined $Cache{"find_in_defaults"}{$Header}) {
6825 return $Cache{"find_in_defaults"}{$Header};
6826 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006827 foreach my $Dir (@DefaultIncPaths,
6828 @DefaultGccPaths,
6829 @DefaultCppPaths,
6830 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006831 {
6832 next if(not $Dir);
6833 if(-f $Dir."/".$Header) {
6834 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6835 }
6836 }
6837 return ($Cache{"find_in_defaults"}{$Header}="");
6838}
6839
6840sub cmp_paths($$)
6841{
6842 my ($Path1, $Path2) = @_;
6843 my @Parts1 = split(/[\/\\]/, $Path1);
6844 my @Parts2 = split(/[\/\\]/, $Path2);
6845 foreach my $Num (0 .. $#Parts1)
6846 {
6847 my $Part1 = $Parts1[$Num];
6848 my $Part2 = $Parts2[$Num];
6849 if($GlibcDir{$Part1}
6850 and not $GlibcDir{$Part2}) {
6851 return 1;
6852 }
6853 elsif($GlibcDir{$Part2}
6854 and not $GlibcDir{$Part1}) {
6855 return -1;
6856 }
6857 elsif($Part1=~/glib/
6858 and $Part2!~/glib/) {
6859 return 1;
6860 }
6861 elsif($Part1!~/glib/
6862 and $Part2=~/glib/) {
6863 return -1;
6864 }
6865 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6866 return $CmpRes;
6867 }
6868 }
6869 return 0;
6870}
6871
6872sub checkRelevance($)
6873{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006874 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006875 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006876
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006877 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006878 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006879 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006880
6881 my $Name = lc(get_filename($Path));
6882 my $Dir = lc(get_dirname($Path));
6883
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006884 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006885
6886 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006887 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006888 my $Len = length($Token);
6889 next if($Len<=1);
6890 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6891 { # include/evolution-data-server-1.4/libebook/e-book.h
6892 return 1;
6893 }
6894 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006895 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006896 return 1;
6897 }
6898 }
6899 return 0;
6900}
6901
6902sub checkFamily(@)
6903{
6904 my @Paths = @_;
6905 return 1 if($#Paths<=0);
6906 my %Prefix = ();
6907 foreach my $Path (@Paths)
6908 {
6909 if($SystemRoot) {
6910 $Path = cut_path_prefix($Path, $SystemRoot);
6911 }
6912 if(my $Dir = get_dirname($Path))
6913 {
6914 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6915 $Prefix{$Dir} += 1;
6916 $Prefix{get_dirname($Dir)} += 1;
6917 }
6918 }
6919 foreach (sort keys(%Prefix))
6920 {
6921 if(get_depth($_)>=3
6922 and $Prefix{$_}==$#Paths+1) {
6923 return 1;
6924 }
6925 }
6926 return 0;
6927}
6928
6929sub isAcceptable($$$)
6930{
6931 my ($Header, $Candidate, $LibVersion) = @_;
6932 my $HName = get_filename($Header);
6933 if(get_dirname($Header))
6934 { # with prefix
6935 return 1;
6936 }
6937 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6938 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6939 return 1;
6940 }
6941 if(checkRelevance($Candidate))
6942 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6943 return 1;
6944 }
6945 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6946 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6947 # /usr/include/qt4/Qt/qsslconfiguration.h
6948 return 1;
6949 }
6950 if($OStarget eq "symbian")
6951 {
6952 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6953 return 1;
6954 }
6955 }
6956 return 0;
6957}
6958
6959sub isRelevant($$$)
6960{ # disallow to search for "abstract" headers in too deep directories
6961 my ($Header, $Candidate, $LibVersion) = @_;
6962 my $HName = get_filename($Header);
6963 if($OStarget eq "symbian")
6964 {
6965 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6966 return 0;
6967 }
6968 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006969 if($OStarget ne "bsd")
6970 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006971 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6972 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6973 return 0;
6974 }
6975 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006976 if($OStarget ne "windows")
6977 {
6978 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6979 { # skip /usr/include/wine/msvcrt
6980 return 0;
6981 }
6982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006983 if(not get_dirname($Header)
6984 and $Candidate=~/[\/\\]wx[\/\\]/)
6985 { # do NOT search in system /wx/ directory
6986 # for headers without a prefix: sstream.h
6987 return 0;
6988 }
6989 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6990 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6991 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6992 return 0;
6993 }
6994 if($Candidate=~/[\/\\]asm-/
6995 and (my $Arch = getArch($LibVersion)) ne "unknown")
6996 { # arch-specific header files
6997 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6998 {# skip ../asm-arm/ if using x86 architecture
6999 return 0;
7000 }
7001 }
7002 my @Candidates = getSystemHeaders($HName, $LibVersion);
7003 if($#Candidates==1)
7004 { # unique header
7005 return 1;
7006 }
7007 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7008 if($#SCandidates==1)
7009 { # unique name
7010 return 1;
7011 }
7012 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7013 if(get_depth($Candidate)-$SystemDepth>=5)
7014 { # abstract headers in too deep directories
7015 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7016 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7017 return 0;
7018 }
7019 }
7020 if($Header eq "parser.h"
7021 and $Candidate!~/\/libxml2\//)
7022 { # select parser.h from xml2 library
7023 return 0;
7024 }
7025 if(not get_dirname($Header)
7026 and keys(%{$SystemHeaders{$HName}})>=3)
7027 { # many headers with the same name
7028 # like thread.h included without a prefix
7029 if(not checkFamily(@Candidates)) {
7030 return 0;
7031 }
7032 }
7033 return 1;
7034}
7035
7036sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007037{ # cache function
7038 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7039 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7040 }
7041 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7042}
7043
7044sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007045{
7046 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007047 if(-f $Header) {
7048 return $Header;
7049 }
7050 if(is_abs($Header) and not -f $Header)
7051 { # incorrect absolute path
7052 return "";
7053 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007054 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007055 { # too abstract configuration headers
7056 return "";
7057 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007058 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007059 if($OSgroup ne "windows")
7060 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007061 if(defined $WinHeaders{lc($HName)}
7062 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007063 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007064 return "";
7065 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007066 }
7067 if($OSgroup ne "macos")
7068 {
7069 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007070 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007071 return "";
7072 }
7073 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007074
7075 if(defined $ObsoleteHeaders{$HName})
7076 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007077 return "";
7078 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007079 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7080 {
7081 if(defined $AlienHeaders{$HName}
7082 or defined $AlienHeaders{$Header})
7083 { # alien headers from other systems
7084 return "";
7085 }
7086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007087
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007088 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007089 { # search in default paths
7090 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007091 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007092 }
7093 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007094 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007095 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007096 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007097 }
7098 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7099 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7100 {
7101 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007102 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007103 }
7104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007105 # error
7106 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007107}
7108
7109sub getSystemHeaders($$)
7110{
7111 my ($Header, $LibVersion) = @_;
7112 my @Candidates = ();
7113 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007115 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007116 next;
7117 }
7118 push(@Candidates, $Candidate);
7119 }
7120 return @Candidates;
7121}
7122
7123sub cut_path_prefix($$)
7124{
7125 my ($Path, $Prefix) = @_;
7126 return $Path if(not $Prefix);
7127 $Prefix=~s/[\/\\]+\Z//;
7128 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7129 return $Path;
7130}
7131
7132sub is_default_include_dir($)
7133{
7134 my $Dir = $_[0];
7135 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007136 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007137}
7138
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007139sub identifyHeader($$)
7140{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007141 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007142 if(not $Header) {
7143 return "";
7144 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007145 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007146 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7147 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007149 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007150}
7151
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007152sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007153{ # search for header by absolute path, relative path or name
7154 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 if(-f $Header)
7156 { # it's relative or absolute path
7157 return get_abs_path($Header);
7158 }
7159 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7160 and my $HeaderDir = find_in_defaults($Header))
7161 { # search for libc headers in the /usr/include
7162 # for non-libc target library before searching
7163 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007164 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007165 }
7166 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7167 { # search in the target library paths
7168 return $Path;
7169 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007170 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007171 { # search in the internal GCC include paths
7172 return $DefaultGccHeader{$Header};
7173 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007174 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007175 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007176 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007177 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007178 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007179 { # search in the default G++ include paths
7180 return $DefaultCppHeader{$Header};
7181 }
7182 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7183 { # search everywhere in the system
7184 return $AnyPath;
7185 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007186 elsif($OSgroup eq "macos")
7187 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7188 if(my $Dir = get_dirname($Header))
7189 {
7190 my $RelPath = "Headers\/".get_filename($Header);
7191 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007192 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007193 }
7194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007195 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007196 # cannot find anything
7197 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007198}
7199
7200sub getLocation($)
7201{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007202 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7203 {
7204 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007205 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007207 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007208 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007209}
7210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211sub getNameByInfo($)
7212{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007213 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007214 {
7215 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7216 {
7217 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7218 {
7219 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7220 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007221 my $Str = $1;
7222 if($CppMode{$Version}
7223 and $Str=~/\Ac99_(.+)\Z/)
7224 {
7225 if($CppKeywords_A{$1}) {
7226 $Str=$1;
7227 }
7228 }
7229 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007230 }
7231 }
7232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007233 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007234 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235}
7236
7237sub getTreeStr($)
7238{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007239 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007240 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007241 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7242 {
7243 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007244 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007245 and $Str=~/\Ac99_(.+)\Z/)
7246 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007247 if($CppKeywords_A{$1}) {
7248 $Str=$1;
7249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007250 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007251 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007254 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255}
7256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007257sub getFuncShortName($)
7258{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007259 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007260 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007261 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007262 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007263 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007264 {
7265 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7266 {
7267 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7268 return "operator ".$RName;
7269 }
7270 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007271 }
7272 else
7273 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007274 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7275 {
7276 if(my $Ind = $Operator_Indication{$1}) {
7277 return "operator".$Ind;
7278 }
7279 elsif(not $UnknownOperator{$1})
7280 {
7281 printMsg("WARNING", "unknown operator $1");
7282 $UnknownOperator{$1} = 1;
7283 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007284 }
7285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007286 }
7287 else
7288 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007289 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7290 return getTreeStr($1);
7291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007292 }
7293 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007294 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007295}
7296
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007297sub getFuncReturn($)
7298{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007299 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7300 {
7301 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7302 {
7303 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7304 return $1;
7305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306 }
7307 }
7308 return "";
7309}
7310
7311sub getFuncOrig($)
7312{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007313 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7314 {
7315 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7316 return $1;
7317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007318 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007319 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007320}
7321
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007322sub unmangleArray(@)
7323{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007324 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007325 { # MSVC mangling
7326 my $UndNameCmd = get_CmdPath("undname");
7327 if(not $UndNameCmd) {
7328 exitStatus("Not_Found", "can't find \"undname\"");
7329 }
7330 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007331 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007332 }
7333 else
7334 { # GCC mangling
7335 my $CppFiltCmd = get_CmdPath("c++filt");
7336 if(not $CppFiltCmd) {
7337 exitStatus("Not_Found", "can't find c++filt in PATH");
7338 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007339 if(not defined $CPPFILT_SUPPORT_FILE)
7340 {
7341 my $Info = `$CppFiltCmd -h 2>&1`;
7342 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7343 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007344 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007345 if($CPPFILT_SUPPORT_FILE)
7346 { # new versions of c++filt can take a file
7347 if($#_>$MAX_CPPFILT_FILE_SIZE)
7348 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7349 # this is fixed in the oncoming version of Binutils
7350 my @Half = splice(@_, 0, ($#_+1)/2);
7351 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007352 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007353 else
7354 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007355 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7356 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7357 if($?==139)
7358 { # segmentation fault
7359 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7360 }
7361 return split(/\n/, $Res);
7362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007363 }
7364 else
7365 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007366 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7367 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007368 my @Half = splice(@_, 0, ($#_+1)/2);
7369 return (unmangleArray(@Half), unmangleArray(@_))
7370 }
7371 else
7372 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007373 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007374 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7375 if($?==139)
7376 { # segmentation fault
7377 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7378 }
7379 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007380 }
7381 }
7382 }
7383}
7384
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385sub get_ChargeLevel($$)
7386{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007387 my ($Symbol, $LibVersion) = @_;
7388 return "" if($Symbol!~/\A(_Z|\?)/);
7389 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7390 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007392 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007393 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007394 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007395 return "[in-charge]";
7396 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007397 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007398 return "[not-in-charge]";
7399 }
7400 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007401 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007402 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007403 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404 return "[in-charge]";
7405 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007406 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007407 return "[not-in-charge]";
7408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007409 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 return "[in-charge-deleting]";
7411 }
7412 }
7413 }
7414 else
7415 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007416 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007417 return "[in-charge]";
7418 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007419 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 return "[not-in-charge]";
7421 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007422 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007423 return "[in-charge]";
7424 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007425 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007426 return "[not-in-charge]";
7427 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007428 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007429 return "[in-charge-deleting]";
7430 }
7431 }
7432 return "";
7433}
7434
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007435sub get_Signature_M($$)
7436{
7437 my ($Symbol, $LibVersion) = @_;
7438 my $Signature_M = $tr_name{$Symbol};
7439 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7440 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007441 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007442 }
7443 return $Signature_M;
7444}
7445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007446sub get_Signature($$)
7447{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007448 my ($Symbol, $LibVersion) = @_;
7449 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7450 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007452 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007453 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007454
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007455 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007456
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007457 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007459 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7460 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007461 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7462 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007463
7464 if(index($Symbol, "_ZTV")==0) {
7465 return "vtable for $ClassName [data]";
7466 }
7467
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007468 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007469 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7470 $Signature .= "~";
7471 }
7472 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007474 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007475 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476 }
7477 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007478 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007479 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007480 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7481 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007482 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007483 else
7484 {
7485 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007486 }
7487 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007488 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007489 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007490 if($Pos eq "") {
7491 next;
7492 }
7493
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007494 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007495 if(not $ParamTypeId) {
7496 next;
7497 }
7498
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007499 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007500 if(not $ParamTypeName) {
7501 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7502 }
7503 foreach my $Typedef (keys(%ChangedTypedef))
7504 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007505 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7506 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007509 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7510 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007511 if($ParamName eq "this"
7512 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007513 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007514 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007515 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007516 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007517 }
7518 else {
7519 push(@ParamArray, $ParamTypeName);
7520 }
7521 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007522 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7523 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007524 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007525 }
7526 else
7527 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007528 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007529 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007530 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007531 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007532 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007533 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7534 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007535 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007537 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7538 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007539 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007540 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007541 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7542 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007543 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007544 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007545 }
7546 }
7547 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007548 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007549 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 }
7551 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007552 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007553 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007554 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555}
7556
7557sub create_member_decl($$)
7558{
7559 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007560 if($TName=~/\([\*]+\)/)
7561 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007562 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7563 return $TName;
7564 }
7565 else
7566 {
7567 my @ArraySizes = ();
7568 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7569 push(@ArraySizes, $1);
7570 }
7571 return $TName." ".$Member.join("", @ArraySizes);
7572 }
7573}
7574
7575sub getFuncType($)
7576{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007577 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7578 {
7579 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7580 {
7581 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7582 {
7583 if($Type eq "method_type") {
7584 return "Method";
7585 }
7586 elsif($Type eq "function_type") {
7587 return "Function";
7588 }
7589 else {
7590 return "Other";
7591 }
7592 }
7593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007595 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007596}
7597
7598sub getFuncTypeId($)
7599{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007600 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7601 {
7602 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7603 return $1;
7604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007605 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007606 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007607}
7608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007609sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007610{ # "._N" or "$_N" in older GCC versions
7611 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007612}
7613
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007614sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007615{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007616 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7617 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007618 }
7619
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007620 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007621
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007622 if($_[1] ne "S")
7623 {
7624 $N=~s/\A[ ]+//g;
7625 $N=~s/[ ]+\Z//g;
7626 $N=~s/[ ]{2,}/ /g;
7627 }
7628
7629 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007630
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007631 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7632
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007633 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007634
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007635 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7636 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007637
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007638 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007639
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007640 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007641
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007642 if($_[1] eq "S")
7643 {
7644 if(index($N, "operator")!=-1) {
7645 $N=~s/\b(operator[ ]*)> >/$1>>/;
7646 }
7647 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007648
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007649 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007650
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007651 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007652}
7653
7654sub get_HeaderDeps($$)
7655{
7656 my ($AbsPath, $LibVersion) = @_;
7657 return () if(not $AbsPath or not $LibVersion);
7658 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7659 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7660 }
7661 my %IncDir = ();
7662 detect_recursive_includes($AbsPath, $LibVersion);
7663 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7664 {
7665 next if(not $HeaderPath);
7666 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7667 my $Dir = get_dirname($HeaderPath);
7668 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7669 {
7670 my $Dep = $Dir;
7671 if($Prefix)
7672 {
7673 if($OSgroup eq "windows")
7674 { # case insensitive seach on windows
7675 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7676 next;
7677 }
7678 }
7679 elsif($OSgroup eq "macos")
7680 { # seach in frameworks
7681 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7682 {
7683 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7684 {# frameworks
7685 my ($HFramework, $HName) = ($1, $2);
7686 $Dep = $HFramework;
7687 }
7688 else
7689 {# mismatch
7690 next;
7691 }
7692 }
7693 }
7694 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7695 { # Linux, FreeBSD
7696 next;
7697 }
7698 }
7699 if(not $Dep)
7700 { # nothing to include
7701 next;
7702 }
7703 if(is_default_include_dir($Dep))
7704 { # included by the compiler
7705 next;
7706 }
7707 if(get_depth($Dep)==1)
7708 { # too short
7709 next;
7710 }
7711 if(isLibcDir($Dep))
7712 { # do NOT include /usr/include/{sys,bits}
7713 next;
7714 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007715 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007716 }
7717 }
7718 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7719 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7720}
7721
7722sub sortIncPaths($$)
7723{
7724 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007725 if(not $ArrRef or $#{$ArrRef}<0) {
7726 return $ArrRef;
7727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007728 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7729 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007730 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007731 return $ArrRef;
7732}
7733
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007734sub sortDeps($$$)
7735{
7736 if($Header_Dependency{$_[2]}{$_[0]}
7737 and not $Header_Dependency{$_[2]}{$_[1]}) {
7738 return 1;
7739 }
7740 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7741 and $Header_Dependency{$_[2]}{$_[1]}) {
7742 return -1;
7743 }
7744 return 0;
7745}
7746
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007747sub join_P($$)
7748{
7749 my $S = "/";
7750 if($OSgroup eq "windows") {
7751 $S = "\\";
7752 }
7753 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007754}
7755
7756sub get_namespace_additions($)
7757{
7758 my $NameSpaces = $_[0];
7759 my ($Additions, $AddNameSpaceId) = ("", 1);
7760 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7761 {
7762 next if($SkipNameSpaces{$Version}{$NS});
7763 next if(not $NS or $NameSpaces->{$NS}==-1);
7764 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7765 next if($NS=~/\A__/i);
7766 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007767 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007768 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7769 my @NS_Parts = split(/::/, $NS);
7770 next if($#NS_Parts==-1);
7771 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7772 foreach my $NS_Part (@NS_Parts)
7773 {
7774 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7775 $TypeDecl_Suffix .= "}";
7776 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007777 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007778 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7779 $Additions.=" $TypeDecl\n $FuncDecl\n";
7780 $AddNameSpaceId+=1;
7781 }
7782 return $Additions;
7783}
7784
7785sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007786{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007787 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007788 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007789 if($Fmt eq "windows")
7790 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007791 $Path=~s/\//\\/g;
7792 $Path=lc($Path);
7793 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007794 else
7795 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007796 $Path=~s/\\/\//g;
7797 }
7798 return $Path;
7799}
7800
7801sub inc_opt($$)
7802{
7803 my ($Path, $Style) = @_;
7804 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007805 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007806 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007807 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007808 return "-I\"".path_format($Path, "unix")."\"";
7809 }
7810 elsif($OSgroup eq "macos"
7811 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007812 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007813 return "-F".esc(get_dirname($Path));
7814 }
7815 else {
7816 return "-I".esc($Path);
7817 }
7818 }
7819 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007820 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007821 }
7822 return "";
7823}
7824
7825sub platformSpecs($)
7826{
7827 my $LibVersion = $_[0];
7828 my $Arch = getArch($LibVersion);
7829 if($OStarget eq "symbian")
7830 { # options for GCCE compiler
7831 my %Symbian_Opts = map {$_=>1} (
7832 "-D__GCCE__",
7833 "-DUNICODE",
7834 "-fexceptions",
7835 "-D__SYMBIAN32__",
7836 "-D__MARM_INTERWORK__",
7837 "-D_UNICODE",
7838 "-D__S60_50__",
7839 "-D__S60_3X__",
7840 "-D__SERIES60_3X__",
7841 "-D__EPOC32__",
7842 "-D__MARM__",
7843 "-D__EABI__",
7844 "-D__MARM_ARMV5__",
7845 "-D__SUPPORT_CPP_EXCEPTIONS__",
7846 "-march=armv5t",
7847 "-mapcs",
7848 "-mthumb-interwork",
7849 "-DEKA2",
7850 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7851 );
7852 return join(" ", keys(%Symbian_Opts));
7853 }
7854 elsif($OSgroup eq "windows"
7855 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7856 { # add options to MinGW compiler
7857 # to simulate the MSVC compiler
7858 my %MinGW_Opts = map {$_=>1} (
7859 "-D_WIN32",
7860 "-D_STDCALL_SUPPORTED",
7861 "-D__int64=\"long long\"",
7862 "-D__int32=int",
7863 "-D__int16=short",
7864 "-D__int8=char",
7865 "-D__possibly_notnullterminated=\" \"",
7866 "-D__nullterminated=\" \"",
7867 "-D__nullnullterminated=\" \"",
7868 "-D__w64=\" \"",
7869 "-D__ptr32=\" \"",
7870 "-D__ptr64=\" \"",
7871 "-D__forceinline=inline",
7872 "-D__inline=inline",
7873 "-D__uuidof(x)=IID()",
7874 "-D__try=",
7875 "-D__except(x)=",
7876 "-D__declspec(x)=__attribute__((x))",
7877 "-D__pragma(x)=",
7878 "-D_inline=inline",
7879 "-D__forceinline=__inline",
7880 "-D__stdcall=__attribute__((__stdcall__))",
7881 "-D__cdecl=__attribute__((__cdecl__))",
7882 "-D__fastcall=__attribute__((__fastcall__))",
7883 "-D__thiscall=__attribute__((__thiscall__))",
7884 "-D_stdcall=__attribute__((__stdcall__))",
7885 "-D_cdecl=__attribute__((__cdecl__))",
7886 "-D_fastcall=__attribute__((__fastcall__))",
7887 "-D_thiscall=__attribute__((__thiscall__))",
7888 "-DSHSTDAPI_(x)=x",
7889 "-D_MSC_EXTENSIONS",
7890 "-DSECURITY_WIN32",
7891 "-D_MSC_VER=1500",
7892 "-D_USE_DECLSPECS_FOR_SAL",
7893 "-D__noop=\" \"",
7894 "-DDECLSPEC_DEPRECATED=\" \"",
7895 "-D__builtin_alignof(x)=__alignof__(x)",
7896 "-DSORTPP_PASS");
7897 if($Arch eq "x86") {
7898 $MinGW_Opts{"-D_M_IX86=300"}=1;
7899 }
7900 elsif($Arch eq "x86_64") {
7901 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7902 }
7903 elsif($Arch eq "ia64") {
7904 $MinGW_Opts{"-D_M_IA64=300"}=1;
7905 }
7906 return join(" ", keys(%MinGW_Opts));
7907 }
7908 return "";
7909}
7910
7911my %C_Structure = map {$_=>1} (
7912# FIXME: Can't separate union and struct data types before dumping,
7913# so it sometimes cause compilation errors for unknown reason
7914# when trying to declare TYPE* tmp_add_class_N
7915# This is a list of such structures + list of other C structures
7916 "sigval",
7917 "sigevent",
7918 "sigaction",
7919 "sigvec",
7920 "sigstack",
7921 "timeval",
7922 "timezone",
7923 "rusage",
7924 "rlimit",
7925 "wait",
7926 "flock",
7927 "stat",
7928 "_stat",
7929 "stat32",
7930 "_stat32",
7931 "stat64",
7932 "_stat64",
7933 "_stati64",
7934 "if_nameindex",
7935 "usb_device",
7936 "sigaltstack",
7937 "sysinfo",
7938 "timeLocale",
7939 "tcp_debug",
7940 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007941 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007942 "timespec",
7943 "random_data",
7944 "drand48_data",
7945 "_IO_marker",
7946 "_IO_FILE",
7947 "lconv",
7948 "sched_param",
7949 "tm",
7950 "itimerspec",
7951 "_pthread_cleanup_buffer",
7952 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007953 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007954 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007955 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007956 "sigcontext",
7957 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007958 # Mac
7959 "_timex",
7960 "_class_t",
7961 "_category_t",
7962 "_class_ro_t",
7963 "_protocol_t",
7964 "_message_ref_t",
7965 "_super_message_ref_t",
7966 "_ivar_t",
7967 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007968);
7969
7970sub getCompileCmd($$$)
7971{
7972 my ($Path, $Opt, $Inc) = @_;
7973 my $GccCall = $GCC_PATH;
7974 if($Opt) {
7975 $GccCall .= " ".$Opt;
7976 }
7977 $GccCall .= " -x ";
7978 if($OSgroup eq "macos") {
7979 $GccCall .= "objective-";
7980 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007981
7982 if($EMERGENCY_MODE_48)
7983 { # workaround for GCC 4.8 (C only)
7984 $GccCall .= "c++";
7985 }
7986 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007987 { # compile as "C++" header
7988 # to obtain complete dump using GCC 4.0
7989 $GccCall .= "c++-header";
7990 }
7991 else
7992 { # compile as "C++" source
7993 # GCC 3.3 cannot compile headers
7994 $GccCall .= "c++";
7995 }
7996 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007997 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007998 $GccCall .= " ".$Opts;
7999 }
8000 # allow extra qualifications
8001 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008002 $GccCall .= " -fpermissive";
8003 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008004 if($NoStdInc)
8005 {
8006 $GccCall .= " -nostdinc";
8007 $GccCall .= " -nostdinc++";
8008 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008009 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008010 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008011 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008012 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008013 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008014 if($Inc)
8015 { # include paths
8016 $GccCall .= " ".$Inc;
8017 }
8018 return $GccCall;
8019}
8020
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008021sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008022{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008023 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008024 my %HeaderElems = (
8025 # Types
8026 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008027 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008028 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8029 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008030 "time.h" => ["time_t"],
8031 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008032 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8033 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008034 "stdbool.h" => ["_Bool"],
8035 "rpc/xdr.h" => ["bool_t"],
8036 "in_systm.h" => ["n_long", "n_short"],
8037 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008038 "arpa/inet.h" => ["fw_src", "ip_src"],
8039 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008040 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008041 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008042 );
8043 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008044 foreach (keys(%HeaderElems))
8045 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008046 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008047 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008048 }
8049 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008050 my %Types = ();
8051 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8052 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008053 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008054 }
8055 if(keys(%Types))
8056 {
8057 my %AddHeaders = ();
8058 foreach my $Type (keys(%Types))
8059 {
8060 if(my $Header = $AutoPreamble{$Type})
8061 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008062 if(my $Path = identifyHeader($Header, $LibVersion))
8063 {
8064 if(skipHeader($Path, $LibVersion)) {
8065 next;
8066 }
8067 $Path = path_format($Path, $OSgroup);
8068 $AddHeaders{$Path}{"Type"} = $Type;
8069 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008070 }
8071 }
8072 }
8073 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008074 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008075 }
8076 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008077 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008078}
8079
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008080sub checkCTags($)
8081{
8082 my $Path = $_[0];
8083 if(not $Path) {
8084 return;
8085 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008086 my $CTags = undef;
8087
8088 if($OSgroup eq "bsd")
8089 { # use ectags on BSD
8090 $CTags = get_CmdPath("ectags");
8091 if(not $CTags) {
8092 printMsg("WARNING", "can't find \'ectags\' program");
8093 }
8094 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008095 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008096 $CTags = get_CmdPath("ctags");
8097 }
8098 if(not $CTags)
8099 {
8100 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008101 return;
8102 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008103
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008104 if($OSgroup ne "linux")
8105 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008106 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8107 if($Info!~/exuberant/i)
8108 {
8109 printMsg("WARNING", "incompatible version of \'ctags\' program");
8110 return;
8111 }
8112 }
8113
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008114 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008115 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008116 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008117 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008118 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008119 open(CTAGS, "<", $Out);
8120 while(my $Line = <CTAGS>)
8121 {
8122 chomp($Line);
8123 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008124 if(defined $Intrinsic_Keywords{$Name})
8125 { # noise
8126 next;
8127 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008128 if($Type eq "n")
8129 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008130 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008131 next;
8132 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008133 if(index($Scpe, "struct:")==0) {
8134 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008135 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008136 if(index($Scpe, "namespace:")==0)
8137 {
8138 if($Scpe=~s/\Anamespace://) {
8139 $Name = $Scpe."::".$Name;
8140 }
8141 }
8142 $TUnit_NameSpaces{$Version}{$Name} = 1;
8143 }
8144 elsif($Type eq "p")
8145 {
8146 if(not $Scpe or index($Scpe, "namespace:")==0) {
8147 $TUnit_Funcs{$Version}{$Name} = 1;
8148 }
8149 }
8150 elsif($Type eq "x")
8151 {
8152 if(not $Scpe or index($Scpe, "namespace:")==0) {
8153 $TUnit_Vars{$Version}{$Name} = 1;
8154 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008155 }
8156 }
8157 close(CTAGS);
8158}
8159
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008160sub preChange($$)
8161{
8162 my ($HeaderPath, $IncStr) = @_;
8163
8164 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8165 my $Content = undef;
8166
8167 if($OStarget eq "windows"
8168 and get_dumpmachine($GCC_PATH)=~/mingw/i
8169 and $MinGWMode{$Version}!=-1)
8170 { # modify headers to compile by MinGW
8171 if(not $Content)
8172 { # preprocessing
8173 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8174 }
8175 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8176 { # __asm { ... }
8177 $MinGWMode{$Version}=1;
8178 }
8179 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8180 { # comments after preprocessing
8181 $MinGWMode{$Version}=1;
8182 }
8183 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8184 { # 0xffui8
8185 $MinGWMode{$Version}=1;
8186 }
8187
8188 if($MinGWMode{$Version}) {
8189 printMsg("INFO", "Using MinGW compatibility mode");
8190 }
8191 }
8192
8193 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8194 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8195 { # rename C++ keywords in C code
8196 # disable this code by -cpp-compatible option
8197 if(not $Content)
8198 { # preprocessing
8199 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8200 }
8201 my $RegExp_C = join("|", keys(%CppKeywords_C));
8202 my $RegExp_F = join("|", keys(%CppKeywords_F));
8203 my $RegExp_O = join("|", keys(%CppKeywords_O));
8204
8205 my $Detected = undef;
8206
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008207 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 +04008208 { # MATCH:
8209 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008210 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008211 # unsigned private: 8;
8212 # DO NOT MATCH:
8213 # #pragma GCC visibility push(default)
8214 $CppMode{$Version} = 1;
8215 $Detected = "$1$2$3$4" if(not defined $Detected);
8216 }
8217 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8218 { # MATCH:
8219 # int delete(...);
8220 # int explicit(...);
8221 # DO NOT MATCH:
8222 # void operator delete(...)
8223 $CppMode{$Version} = 1;
8224 $Detected = "$1$2$3" if(not defined $Detected);
8225 }
8226 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8227 { # MATCH:
8228 # int bool;
8229 # DO NOT MATCH:
8230 # bool X;
8231 # return *this;
8232 # throw;
8233 $CppMode{$Version} = 1;
8234 $Detected = "$1$2$3" if(not defined $Detected);
8235 }
8236 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8237 { # MATCH:
8238 # int operator(...);
8239 # DO NOT MATCH:
8240 # int operator()(...);
8241 $CppMode{$Version} = 1;
8242 $Detected = "$1$2$3" if(not defined $Detected);
8243 }
8244 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8245 { # MATCH:
8246 # int foo(int operator);
8247 # int foo(int operator, int other);
8248 # DO NOT MATCH:
8249 # int operator,(...);
8250 $CppMode{$Version} = 1;
8251 $Detected = "$1$2$3" if(not defined $Detected);
8252 }
8253 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8254 { # MATCH:
8255 # int foo(gboolean *bool);
8256 # DO NOT MATCH:
8257 # void setTabEnabled(int index, bool);
8258 $CppMode{$Version} = 1;
8259 $Detected = "$1$2$3" if(not defined $Detected);
8260 }
8261 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8262 { # MATCH:
8263 # int foo(int* this);
8264 # int bar(int this);
8265 # int baz(int throw);
8266 # DO NOT MATCH:
8267 # foo(X, this);
8268 $CppMode{$Version} = 1;
8269 $Detected = "$1$2$3$4" if(not defined $Detected);
8270 }
8271 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8272 { # MATCH:
8273 # struct template {...};
8274 # extern template foo(...);
8275 $CppMode{$Version} = 1;
8276 $Detected = "$1$2" if(not defined $Detected);
8277 }
8278
8279 if($CppMode{$Version} == 1)
8280 {
8281 if($Debug)
8282 {
8283 $Detected=~s/\A\s+//g;
8284 printMsg("INFO", "Detected code: \"$Detected\"");
8285 }
8286 }
8287
8288 # remove typedef enum NAME NAME;
8289 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8290 my $N = 0;
8291 while($N<=$#FwdTypedefs-1)
8292 {
8293 my $S = $FwdTypedefs[$N];
8294 if($S eq $FwdTypedefs[$N+1])
8295 {
8296 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008297 $CppMode{$Version} = 1;
8298
8299 if($Debug) {
8300 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8301 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008302 }
8303 $N+=2;
8304 }
8305
8306 if($CppMode{$Version}==1) {
8307 printMsg("INFO", "Using C++ compatibility mode");
8308 }
8309 }
8310
8311 if($CppMode{$Version}==1
8312 or $MinGWMode{$Version}==1)
8313 {
8314 my $IPath = $TMP_DIR."/dump$Version.i";
8315 writeFile($IPath, $Content);
8316 return $IPath;
8317 }
8318
8319 return undef;
8320}
8321
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008322sub getDump()
8323{
8324 if(not $GCC_PATH) {
8325 exitStatus("Error", "internal error - GCC path is not set");
8326 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008327
8328 my @Headers = keys(%{$Registered_Headers{$Version}});
8329 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8330
8331 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8332
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008333 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008334 my $HeaderPath = $TmpHeaderPath;
8335
8336 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008337 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008338 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8339 {
8340 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008341 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008342 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008343 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008344 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8345 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008346 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008347 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008348 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008349 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8350 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008352 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008353 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008354
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008355 if($ExtraInfo)
8356 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008357 if($IncludeString) {
8358 writeFile($ExtraInfo."/include-string", $IncludeString);
8359 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008360 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8361 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008362
8363 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8364 {
8365 my $REDIR = "";
8366 foreach my $P1 (sort @Redirects) {
8367 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8368 }
8369 writeFile($ExtraInfo."/include-redirect", $REDIR);
8370 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008371 }
8372
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008373 if(not keys(%{$TargetHeaders{$Version}}))
8374 { # Target headers
8375 addTargetHeaders($Version);
8376 }
8377
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008378 # clean memory
8379 %RecursiveIncludes = ();
8380 %Header_Include_Prefix = ();
8381 %Header_Includes = ();
8382
8383 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008384 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008385 delete($Cache{"detect_header_includes"});
8386 delete($Cache{"selectSystemHeader"});
8387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008388 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008389 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8390 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008391
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008392 if($ExtraInfo)
8393 { # extra information for other tools
8394 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8395 }
8396
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008397 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008398 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008399 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008400
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008401 if($COMMON_LANGUAGE{$Version} eq "C++") {
8402 checkCTags($Pre);
8403 }
8404
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008405 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8406 { # try to correct the preprocessor output
8407 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008408 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008410 if($COMMON_LANGUAGE{$Version} eq "C++")
8411 { # add classes and namespaces to the dump
8412 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008413 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008414 or $MinGWMode{$Version}==1) {
8415 $CHdump .= " -fpreprocessed";
8416 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008417 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008418 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008419 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008420 chdir($ORIG_DIR);
8421 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8422 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008423 my $Content = readFile($ClassDump);
8424 foreach my $ClassInfo (split(/\n\n/, $Content))
8425 {
8426 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8427 {
8428 my $CName = $1;
8429 next if($CName=~/\A(__|_objc_|_opaque_)/);
8430 $TUnit_NameSpaces{$Version}{$CName} = -1;
8431 if($CName=~/\A[\w:]+\Z/)
8432 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008433 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008434 }
8435 if($CName=~/(\w[\w:]*)::/)
8436 { # namespaces
8437 my $NS = $1;
8438 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8439 $TUnit_NameSpaces{$Version}{$NS} = 1;
8440 }
8441 }
8442 }
8443 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8444 { # read v-tables (advanced approach)
8445 my ($CName, $VTable) = ($1, $2);
8446 $ClassVTable_Content{$Version}{$CName} = $VTable;
8447 }
8448 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008449 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8450 { # add user-defined namespaces
8451 $TUnit_NameSpaces{$Version}{$NS} = 1;
8452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008453 if($Debug)
8454 { # debug mode
8455 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008456 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008457 }
8458 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008459 }
8460
8461 # add namespaces and classes
8462 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8463 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008464 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008465 }
8466 # some GCC versions don't include class methods to the TU dump by default
8467 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008468 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008469 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8470 {
8471 next if($C_Structure{$CName});
8472 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008473 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008474 if(not $Force and $GCC_44
8475 and $OSgroup eq "linux")
8476 { # optimization for linux with GCC >= 4.4
8477 # disable this code by -force option
8478 if(index($CName, "::")!=-1)
8479 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008480 next;
8481 }
8482 }
8483 else
8484 {
8485 if($CName=~/\A(.+)::[^:]+\Z/
8486 and $TUnit_Classes{$Version}{$1})
8487 { # classes inside other classes
8488 next;
8489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008490 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008491 if(defined $TUnit_Funcs{$Version}{$CName})
8492 { # the same name for a function and type
8493 next;
8494 }
8495 if(defined $TUnit_Vars{$Version}{$CName})
8496 { # the same name for a variable and type
8497 next;
8498 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008499 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8500 }
8501 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008502 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008503 }
8504 }
8505 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8506 # create TU dump
8507 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008508 if($UserLang eq "C") {
8509 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8510 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008511 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008512 or $MinGWMode{$Version}==1) {
8513 $TUdump .= " -fpreprocessed";
8514 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008515 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008516 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8517 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008518 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008519 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008520 if($?)
8521 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008522 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008523 { # try to recompile
8524 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008525 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008526 and index($Errors, "c99_")!=-1
8527 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008528 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008529 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008530
8531 if($Debug)
8532 {
8533 # printMsg("INFO", $Errors);
8534 }
8535
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008536 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008537 resetLogging($Version);
8538 $TMP_DIR = tempdir(CLEANUP=>1);
8539 return getDump();
8540 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008541 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008542 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008543 { # add auto preamble headers and try again
8544 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008545 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008546 foreach my $Num (0 .. $#Headers)
8547 {
8548 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008549 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8550 {
8551 push_U($Include_Preamble{$Version}, $Path);
8552 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008553 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008554 }
8555 resetLogging($Version);
8556 $TMP_DIR = tempdir(CLEANUP=>1);
8557 return getDump();
8558 }
8559 elsif($Cpp0xMode{$Version}!=-1
8560 and ($Errors=~/\Q-std=c++0x\E/
8561 or $Errors=~/is not a class or namespace/))
8562 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008563 if(check_gcc($GCC_PATH, "4.6"))
8564 {
8565 $Cpp0xMode{$Version}=-1;
8566 printMsg("INFO", "Enabling c++0x mode");
8567 resetLogging($Version);
8568 $TMP_DIR = tempdir(CLEANUP=>1);
8569 $CompilerOptions{$Version} .= " -std=c++0x";
8570 return getDump();
8571 }
8572 else {
8573 printMsg("WARNING", "Probably c++0x construction detected");
8574 }
8575
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008576 }
8577 elsif($MinGWMode{$Version}==1)
8578 { # disable MinGW mode and try again
8579 $MinGWMode{$Version}=-1;
8580 resetLogging($Version);
8581 $TMP_DIR = tempdir(CLEANUP=>1);
8582 return getDump();
8583 }
8584 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008585 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008586 else {
8587 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008589 printMsg("ERROR", "some errors occurred when compiling headers");
8590 printErrorLog($Version);
8591 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008592 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008593 }
8594 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008595 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008596 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008597
8598 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8599 return $TUs[0];
8600 }
8601 else
8602 {
8603 my $Msg = "can't compile header(s)";
8604 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8605 $Msg .= "\nDid you install G++?";
8606 }
8607 exitStatus("Cannot_Compile", $Msg);
8608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008609}
8610
8611sub cmd_file($)
8612{
8613 my $Path = $_[0];
8614 return "" if(not $Path or not -e $Path);
8615 if(my $CmdPath = get_CmdPath("file")) {
8616 return `$CmdPath -b \"$Path\"`;
8617 }
8618 return "";
8619}
8620
8621sub getIncString($$)
8622{
8623 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008624 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008625 my $String = "";
8626 foreach (@{$ArrRef}) {
8627 $String .= " ".inc_opt($_, $Style);
8628 }
8629 return $String;
8630}
8631
8632sub getIncPaths(@)
8633{
8634 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008635 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008636 if($INC_PATH_AUTODETECT{$Version})
8637 { # auto-detecting dependencies
8638 my %Includes = ();
8639 foreach my $HPath (@HeaderPaths)
8640 {
8641 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8642 {
8643 if($Skip_Include_Paths{$Version}{$Dir}) {
8644 next;
8645 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008646 if($SystemRoot)
8647 {
8648 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8649 next;
8650 }
8651 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008652 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008653 }
8654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008655 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008656 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008657 }
8658 }
8659 else
8660 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008661 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008662 }
8663 return \@IncPaths;
8664}
8665
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008666sub push_U($@)
8667{ # push unique
8668 if(my $Array = shift @_)
8669 {
8670 if(@_)
8671 {
8672 my %Exist = map {$_=>1} @{$Array};
8673 foreach my $Elem (@_)
8674 {
8675 if(not defined $Exist{$Elem})
8676 {
8677 push(@{$Array}, $Elem);
8678 $Exist{$Elem} = 1;
8679 }
8680 }
8681 }
8682 }
8683}
8684
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008685sub callPreprocessor($$$)
8686{
8687 my ($Path, $Inc, $LibVersion) = @_;
8688 return "" if(not $Path or not -f $Path);
8689 my $IncludeString=$Inc;
8690 if(not $Inc) {
8691 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8692 }
8693 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008694 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008695 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008696 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008697}
8698
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008699sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008700{ # native "find" is much faster than File::Find (~6x)
8701 # also the File::Find doesn't support --maxdepth N option
8702 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008703 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008704 return () if(not $Path or not -e $Path);
8705 if($OSgroup eq "windows")
8706 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008707 $Path = get_abs_path($Path);
8708 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008709 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 if($MaxDepth!=1) {
8711 $Cmd .= " /S";
8712 }
8713 if($Type eq "d") {
8714 $Cmd .= " /AD";
8715 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008716 elsif($Type eq "f") {
8717 $Cmd .= " /A-D";
8718 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008719 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008721 {
8722 if(not $UseRegex)
8723 { # FIXME: how to search file names in MS shell?
8724 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008725 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008726 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008727 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008728 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008729 }
8730 my @AbsPaths = ();
8731 foreach my $File (@Files)
8732 {
8733 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008734 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008735 }
8736 if($Type eq "f" and not -f $File)
8737 { # skip dirs
8738 next;
8739 }
8740 push(@AbsPaths, path_format($File, $OSgroup));
8741 }
8742 if($Type eq "d") {
8743 push(@AbsPaths, $Path);
8744 }
8745 return @AbsPaths;
8746 }
8747 else
8748 {
8749 my $FindCmd = get_CmdPath("find");
8750 if(not $FindCmd) {
8751 exitStatus("Not_Found", "can't find a \"find\" command");
8752 }
8753 $Path = get_abs_path($Path);
8754 if(-d $Path and -l $Path
8755 and $Path!~/\/\Z/)
8756 { # for directories that are symlinks
8757 $Path.="/";
8758 }
8759 my $Cmd = $FindCmd." \"$Path\"";
8760 if($MaxDepth) {
8761 $Cmd .= " -maxdepth $MaxDepth";
8762 }
8763 if($Type) {
8764 $Cmd .= " -type $Type";
8765 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008766 if($Name and not $UseRegex)
8767 { # wildcards
8768 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008770 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008771 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008772 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8773 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008774 my @Files = split(/\n/, $Res);
8775 if($Name and $UseRegex)
8776 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008777 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008778 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008779 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008780 }
8781}
8782
8783sub unpackDump($)
8784{
8785 my $Path = $_[0];
8786 return "" if(not $Path or not -e $Path);
8787 $Path = get_abs_path($Path);
8788 $Path = path_format($Path, $OSgroup);
8789 my ($Dir, $FileName) = separate_path($Path);
8790 my $UnpackDir = $TMP_DIR."/unpack";
8791 rmtree($UnpackDir);
8792 mkpath($UnpackDir);
8793 if($FileName=~s/\Q.zip\E\Z//g)
8794 { # *.zip
8795 my $UnzipCmd = get_CmdPath("unzip");
8796 if(not $UnzipCmd) {
8797 exitStatus("Not_Found", "can't find \"unzip\" command");
8798 }
8799 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008800 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008801 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008802 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008803 }
8804 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008805 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008806 if(not @Contents) {
8807 exitStatus("Error", "can't extract \'$Path\'");
8808 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008809 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008811 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008812 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008813 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008814 if($OSgroup eq "windows")
8815 { # -xvzf option is not implemented in tar.exe (2003)
8816 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8817 my $TarCmd = get_CmdPath("tar");
8818 if(not $TarCmd) {
8819 exitStatus("Not_Found", "can't find \"tar\" command");
8820 }
8821 my $GzipCmd = get_CmdPath("gzip");
8822 if(not $GzipCmd) {
8823 exitStatus("Not_Found", "can't find \"gzip\" command");
8824 }
8825 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008826 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008827 if($?) {
8828 exitStatus("Error", "can't extract \'$Path\'");
8829 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008830 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008831 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008832 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008833 }
8834 chdir($ORIG_DIR);
8835 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008836 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008837 if(not @Contents) {
8838 exitStatus("Error", "can't extract \'$Path\'");
8839 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008840 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008841 }
8842 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008843 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008844 my $TarCmd = get_CmdPath("tar");
8845 if(not $TarCmd) {
8846 exitStatus("Not_Found", "can't find \"tar\" command");
8847 }
8848 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008849 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008851 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 }
8853 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008854 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008855 if(not @Contents) {
8856 exitStatus("Error", "can't extract \'$Path\'");
8857 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008858 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008859 }
8860 }
8861}
8862
8863sub createArchive($$)
8864{
8865 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008866 if(not $To) {
8867 $To = ".";
8868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869 if(not $Path or not -e $Path
8870 or not -d $To) {
8871 return "";
8872 }
8873 my ($From, $Name) = separate_path($Path);
8874 if($OSgroup eq "windows")
8875 { # *.zip
8876 my $ZipCmd = get_CmdPath("zip");
8877 if(not $ZipCmd) {
8878 exitStatus("Not_Found", "can't find \"zip\"");
8879 }
8880 my $Pkg = $To."/".$Name.".zip";
8881 unlink($Pkg);
8882 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008883 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008884 if($?)
8885 { # cannot allocate memory (or other problems with "zip")
8886 unlink($Path);
8887 exitStatus("Error", "can't pack the ABI dump: ".$!);
8888 }
8889 chdir($ORIG_DIR);
8890 unlink($Path);
8891 return $Pkg;
8892 }
8893 else
8894 { # *.tar.gz
8895 my $TarCmd = get_CmdPath("tar");
8896 if(not $TarCmd) {
8897 exitStatus("Not_Found", "can't find \"tar\"");
8898 }
8899 my $GzipCmd = get_CmdPath("gzip");
8900 if(not $GzipCmd) {
8901 exitStatus("Not_Found", "can't find \"gzip\"");
8902 }
8903 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8904 unlink($Pkg);
8905 chdir($From);
8906 system($TarCmd, "-czf", $Pkg, $Name);
8907 if($?)
8908 { # cannot allocate memory (or other problems with "tar")
8909 unlink($Path);
8910 exitStatus("Error", "can't pack the ABI dump: ".$!);
8911 }
8912 chdir($ORIG_DIR);
8913 unlink($Path);
8914 return $To."/".$Name.".tar.gz";
8915 }
8916}
8917
8918sub is_header_file($)
8919{
8920 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8921 return $_[0];
8922 }
8923 return 0;
8924}
8925
8926sub is_not_header($)
8927{
8928 if($_[0]=~/\.\w+\Z/
8929 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8930 return 1;
8931 }
8932 return 0;
8933}
8934
8935sub is_header($$$)
8936{
8937 my ($Header, $UserDefined, $LibVersion) = @_;
8938 return 0 if(-d $Header);
8939 if(-f $Header) {
8940 $Header = get_abs_path($Header);
8941 }
8942 else
8943 {
8944 if(is_abs($Header))
8945 { # incorrect absolute path
8946 return 0;
8947 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008948 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008949 $Header = $HPath;
8950 }
8951 else
8952 { # can't find header
8953 return 0;
8954 }
8955 }
8956 if($Header=~/\.\w+\Z/)
8957 { # have an extension
8958 return is_header_file($Header);
8959 }
8960 else
8961 {
8962 if($UserDefined==2)
8963 { # specified on the command line
8964 if(cmd_file($Header)!~/HTML|XML/i) {
8965 return $Header;
8966 }
8967 }
8968 elsif($UserDefined)
8969 { # specified in the XML-descriptor
8970 # header file without an extension
8971 return $Header;
8972 }
8973 else
8974 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008975 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008976 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008977 { # !~/HTML|XML|shared|dynamic/i
8978 return $Header;
8979 }
8980 }
8981 }
8982 return 0;
8983}
8984
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008985sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008986{
8987 my $LibVersion = $_[0];
8988 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8989 {
8990 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008991 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008992
8993 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8994 detect_recursive_includes($RegHeader, $LibVersion);
8995 }
8996
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008997 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8998 {
8999 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009000
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009001 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009002 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9003 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009004 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009005 }
9006 }
9007 }
9008}
9009
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009010sub familiarDirs($$)
9011{
9012 my ($D1, $D2) = @_;
9013 if($D1 eq $D2) {
9014 return 1;
9015 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009016
9017 my $U1 = index($D1, "/usr/");
9018 my $U2 = index($D2, "/usr/");
9019
9020 if($U1==0 and $U2!=0) {
9021 return 0;
9022 }
9023
9024 if($U2==0 and $U1!=0) {
9025 return 0;
9026 }
9027
9028 if(index($D2, $D1."/")==0) {
9029 return 1;
9030 }
9031
9032 # /usr/include/DIR
9033 # /home/user/DIR
9034
9035 my $DL = get_depth($D1);
9036
9037 my @Dirs1 = ($D1);
9038 while($DL - get_depth($D1)<=2
9039 and get_depth($D1)>=4
9040 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9041 push(@Dirs1, $D1);
9042 }
9043
9044 my @Dirs2 = ($D2);
9045 while(get_depth($D2)>=4
9046 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9047 push(@Dirs2, $D2);
9048 }
9049
9050 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009051 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009052 foreach my $P2 (@Dirs2)
9053 {
9054
9055 if($P1 eq $P2) {
9056 return 1;
9057 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009058 }
9059 }
9060 return 0;
9061}
9062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009063sub readHeaders($)
9064{
9065 $Version = $_[0];
9066 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9067 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009068 if($Debug)
9069 { # debug mode
9070 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009071 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009072 }
9073 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009074}
9075
9076sub prepareTypes($)
9077{
9078 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009079 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009080 { # support for old ABI dumps
9081 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009082 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009084 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9085 if($TName=~/\A(\w+)::(\w+)/) {
9086 my ($P1, $P2) = ($1, $2);
9087 if($P1 eq $P2) {
9088 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009089 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009090 else {
9091 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009093 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009094 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009095 }
9096 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009097 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009098 { # support for old ABI dumps
9099 # V < 2.5: array size == "number of elements"
9100 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009101 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009102 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009103 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009104 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009105 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009106 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009107 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009108 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009109 $Size *= $Base{"Size"};
9110 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009111 }
9112 else
9113 { # array[] is a pointer
9114 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009115 }
9116 }
9117 }
9118 }
9119 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009120 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009121 { # support for old ABI dumps
9122 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009123 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009124 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009125 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009126 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009127 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009128 my %Type = get_Type($TypeId, $LibVersion);
9129 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9130 my %Type2 = get_Type($TypeId_2, $V2);
9131 if($Type{"Size"} ne $Type2{"Size"}) {
9132 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009133 }
9134 }
9135 }
9136 }
9137}
9138
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009139sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009140{
9141 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009142
9143 if(not keys(%{$SymbolInfo{$LibVersion}}))
9144 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009145 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009146 {
9147 if($CheckHeadersOnly) {
9148 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9149 }
9150 else {
9151 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9152 }
9153 }
9154 }
9155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009156 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009157 if(not checkDump(1, "2.10")
9158 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009159 { # different formats
9160 $Remangle = 1;
9161 }
9162 if($CheckHeadersOnly)
9163 { # different languages
9164 if($UserLang)
9165 { # --lang=LANG for both versions
9166 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9167 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9168 {
9169 if($UserLang eq "C++")
9170 { # remangle symbols
9171 $Remangle = 1;
9172 }
9173 elsif($UserLang eq "C")
9174 { # remove mangling
9175 $Remangle = -1;
9176 }
9177 }
9178 }
9179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009180
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009181 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009182 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009183 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009184 { # support for old ABI dumps
9185 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9186 {
9187 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9188 {
9189 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9190 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009191 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009192 if(defined $DVal and $DVal ne "")
9193 {
9194 if($TName eq "char") {
9195 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9196 }
9197 elsif($TName eq "bool") {
9198 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9199 }
9200 }
9201 }
9202 }
9203 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009204 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009205 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009206 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9207 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009208 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009209 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9210 # + support for old ABI dumps
9211 next;
9212 }
9213 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009214 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009215 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009216 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009217 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009218
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009219 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009220 if(not checkDump(1, "2.12")
9221 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009222 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009223 if($ShortName eq "operator>>")
9224 {
9225 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9226 { # corrected mangling of operator>>
9227 $SRemangle = 1;
9228 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009229 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009230 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9231 {
9232 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9233 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9234 { # corrected mangling of const global data
9235 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9236 # and incorrectly mangled by old ACC versions
9237 $SRemangle = 1;
9238 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009239 }
9240 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009241 if(not $CheckHeadersOnly)
9242 { # support for old ABI dumps
9243 if(not checkDump(1, "2.17")
9244 or not checkDump(2, "2.17"))
9245 {
9246 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9247 {
9248 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9249 {
9250 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9251 {
9252 $MnglName = $ShortName;
9253 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9254 }
9255 }
9256 }
9257 }
9258 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009259 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009260 { # support for old ABI dumps: some symbols are not mangled in old dumps
9261 # mangle both sets of symbols (old and new)
9262 # NOTE: remangling all symbols by the same mangler
9263 if($MnglName=~/\A_ZN(V|)K/)
9264 { # mangling may be incorrect on old ABI dumps
9265 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009266 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009267 }
9268 if($MnglName=~/\A_ZN(K|)V/)
9269 { # mangling may be incorrect on old ABI dumps
9270 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009271 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009272 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009273 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9274 or (not $ClassID and $CheckHeadersOnly)
9275 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9276 { # support for old ABI dumps, GCC >= 4.0
9277 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009278 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009279 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009280 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 $MangledNames{$LibVersion}{$MnglName} = 1;
9282 }
9283 }
9284 }
9285 elsif($Remangle==-1)
9286 { # remove mangling
9287 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009288 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009290 if(not $MnglName) {
9291 next;
9292 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009293
9294 # NOTE: duplicated entries in the ABI Dump
9295 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9296 {
9297 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9298 {
9299 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9300 {
9301 next;
9302 }
9303 }
9304 }
9305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009306 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9307 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009308 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9309
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009310 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009311 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009312 { # support for old dumps
9313 # add "Volatile" attribute
9314 if($MnglName=~/_Z(K|)V/) {
9315 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9316 }
9317 }
9318 # symbol and its symlink have same signatures
9319 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009320 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009322
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009323 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9324 {
9325 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009326
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009327 if($SymVer{$LibVersion}{$Alias}) {
9328 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9329 }
9330 }
9331
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009332 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009333 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009334 }
9335 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9336 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9337 }
9338 if($ExtendedCheck)
9339 { # --ext option
9340 addExtension($LibVersion);
9341 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009342
9343 # clean memory
9344 delete($SymbolInfo{$LibVersion});
9345
9346 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009347 { # detect allocable classes with public exported constructors
9348 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009349 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009350 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009351 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009352 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009353 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9354 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009355 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009356 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009357 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009358 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 $AllocableClass{$LibVersion}{$ClassName} = 1;
9360 }
9361 }
9362 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009363 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009364 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009365 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009366 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009367 if($CheckHeadersOnly)
9368 {
9369 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9370 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9371 { # all symbols except non-virtual inline
9372 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9373 }
9374 }
9375 else {
9376 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009377 }
9378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009379 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009380 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009381 }
9382 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009383 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009384 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009385 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009387 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009388 if(defined $Base{"Type"}
9389 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009390 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009391 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 if($Name=~/<([^<>\s]+)>/)
9393 {
9394 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9395 $ReturnedClass{$LibVersion}{$Tid} = 1;
9396 }
9397 }
9398 else {
9399 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9400 }
9401 }
9402 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009403 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009405 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009406 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009407 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009408 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009409 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009410 if($Base{"Type"}=~/Struct|Class/)
9411 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009412 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009413 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9414 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009415 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009416 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009417 }
9418 }
9419 }
9420 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009421
9422 # mapping {short name => symbols}
9423 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009424 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009425 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009426 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009427 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009428 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009429 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009430 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009431 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9432 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009433 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009434 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009435 }
9436 }
9437 }
9438 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009439
9440 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009441 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009442 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009443 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009444 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009445 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9446 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009447 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009448 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009449 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009450 $ClassNames{$LibVersion}{$TName} = 1;
9451 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009453 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9454 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009455 }
9456 }
9457 }
9458 }
9459 }
9460}
9461
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009462sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009464 my ($Tid, $LibVersion) = @_;
9465 if(not $Tid) {
9466 return $Tid;
9467 }
9468
9469 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9470 {
9471 if($TName_Tid{$LibVersion}{$Name}) {
9472 return $TName_Tid{$LibVersion}{$Name};
9473 }
9474 }
9475
9476 return $Tid;
9477}
9478
9479sub register_SymbolUsage($$$)
9480{
9481 my ($InfoId, $UsedType, $LibVersion) = @_;
9482
9483 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9484 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9485 {
9486 register_TypeUsage($RTid, $UsedType, $LibVersion);
9487 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9488 }
9489 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9490 {
9491 register_TypeUsage($FCid, $UsedType, $LibVersion);
9492 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9493
9494 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9495 { # register "this" pointer
9496 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9497 }
9498 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9499 { # register "this" pointer (const method)
9500 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9501 }
9502 }
9503 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9504 {
9505 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9506 {
9507 register_TypeUsage($PTid, $UsedType, $LibVersion);
9508 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9509 }
9510 }
9511 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9512 {
9513 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9514 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9515 register_TypeUsage($TTid, $UsedType, $LibVersion);
9516 }
9517 }
9518}
9519
9520sub register_TypeUsage($$$)
9521{
9522 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009523 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009524 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009525 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009526 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009527 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009528 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009529 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009530
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009531 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009532 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009533 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009534 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009535 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009536 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9537 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9538 }
9539 }
9540
9541 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9542 {
9543 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009544 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009545 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009546 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9547 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009548 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009549 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9550 {
9551 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9552 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009553 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009554 }
9555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009556 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009557 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009558 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009559 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9560 {
9561 register_TypeUsage($MTid, $UsedType, $LibVersion);
9562 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009563 }
9564 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009565 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009566 or $TInfo{"Type"} eq "MethodPtr"
9567 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009568 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009569 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009570 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009571 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009572 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009573 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009574 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9575 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009576 }
9577 }
9578 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009579 if($TInfo{"Type"} eq "FieldPtr")
9580 {
9581 if(my $RTid = $TInfo{"Return"}) {
9582 register_TypeUsage($RTid, $UsedType, $LibVersion);
9583 }
9584 if(my $CTid = $TInfo{"Class"}) {
9585 register_TypeUsage($CTid, $UsedType, $LibVersion);
9586 }
9587 }
9588 if($TInfo{"Type"} eq "MethodPtr")
9589 {
9590 if(my $CTid = $TInfo{"Class"}) {
9591 register_TypeUsage($CTid, $UsedType, $LibVersion);
9592 }
9593 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009594 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009595 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009596 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009597 $UsedType->{$TypeId} = 1;
9598 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9599 {
9600 register_TypeUsage($BTid, $UsedType, $LibVersion);
9601 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9602 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009603 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009604 else
9605 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9606 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009607 }
9608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009609}
9610
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009611sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009612{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009613 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9614
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009615 if($Level eq "Dump")
9616 {
9617 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9618 { # TODO: check if this symbol is from
9619 # base classes of other target symbols
9620 return 1;
9621 }
9622 }
9623
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009624 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9625 { # stdc++ interfaces
9626 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009627 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009628
9629 my $Target = 0;
9630 if(my $Header = $SInfo->{"Header"}) {
9631 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9632 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009633 if($ExtendedCheck)
9634 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009635 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009636 $Target = 1;
9637 }
9638 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009639 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009640 {
9641 if($Target)
9642 {
9643 if($Level eq "Dump")
9644 { # dumped
9645 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009646 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009647 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009648 return 1;
9649 }
9650 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009651 else {
9652 return 1;
9653 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009654 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655 elsif($Level eq "Source")
9656 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009657 return 1;
9658 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009659 elsif($Level eq "Binary")
9660 { # checked
9661 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9662 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9663 return 1;
9664 }
9665 }
9666 }
9667 }
9668 else
9669 { # library is available
9670 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9671 { # exported symbols
9672 return 1;
9673 }
9674 if($Level eq "Dump")
9675 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009676 if($BinaryOnly)
9677 {
9678 if($SInfo->{"Data"})
9679 {
9680 if($Target) {
9681 return 1;
9682 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009683 }
9684 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009685 else
9686 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009687 if($Target) {
9688 return 1;
9689 }
9690 }
9691 }
9692 elsif($Level eq "Source")
9693 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009694 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009695 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009696 { # skip LOCAL symbols
9697 if($Target) {
9698 return 1;
9699 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009700 }
9701 }
9702 elsif($Level eq "Binary")
9703 { # checked
9704 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9705 {
9706 if($Target) {
9707 return 1;
9708 }
9709 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009710 }
9711 }
9712 return 0;
9713}
9714
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009715sub cleanDump($)
9716{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009717 my $LibVersion = $_[0];
9718 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9719 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009720 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9721 {
9722 delete($SymbolInfo{$LibVersion}{$InfoId});
9723 next;
9724 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009725 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009726 if(not $MnglName)
9727 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009728 delete($SymbolInfo{$LibVersion}{$InfoId});
9729 next;
9730 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009731 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009732 if(not $ShortName)
9733 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009734 delete($SymbolInfo{$LibVersion}{$InfoId});
9735 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009737 if($MnglName eq $ShortName)
9738 { # remove duplicate data
9739 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009740 }
9741 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9742 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9743 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009744 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9745 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9746 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009747 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009748 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009749 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009750 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009751 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9752 {
9753 delete($TypeInfo{$LibVersion}{$Tid});
9754 next;
9755 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009756 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009757 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009758 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009759 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9760 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9761 }
9762 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009763 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9764 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9765 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009766 }
9767}
9768
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009769sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009770{
9771 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009772
9773 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9774 {
9775 if(defined $TypeInfo{$LibVersion}{$Dupl})
9776 {
9777 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9778 { # duplicate
9779 return 0;
9780 }
9781 }
9782 }
9783
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009784 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9785
9786 if(isBuiltIn($THeader)) {
9787 return 0;
9788 }
9789
9790 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9791 return 0;
9792 }
9793
9794 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9795 return 0;
9796 }
9797
9798 if(selfTypedef($Tid, $LibVersion)) {
9799 return 0;
9800 }
9801
9802 if(not isTargetType($Tid, $LibVersion)) {
9803 return 0;
9804 }
9805
9806 return 0;
9807}
9808
9809sub isTargetType($$)
9810{
9811 my ($Tid, $LibVersion) = @_;
9812
9813 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9814 { # derived
9815 return 1;
9816 }
9817
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009818 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009819 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009820 if(not is_target_header($THeader, $LibVersion))
9821 { # from target headers
9822 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009823 }
9824 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009825 else
9826 { # NOTE: if type is defined in source
9827 if($UsedDump{$LibVersion}{"Public"})
9828 {
9829 if(isPrivateABI($Tid, $LibVersion)) {
9830 return 0;
9831 }
9832 else {
9833 return 1;
9834 }
9835 }
9836 else {
9837 return 0;
9838 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009839 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009840
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009841 if($SkipInternalTypes)
9842 {
9843 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9844 {
9845 return 0;
9846 }
9847 }
9848
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009849 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009850}
9851
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009852sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009853{ # remove unused data types from the ABI dump
9854 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009855
9856 my %UsedType = ();
9857
9858 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009859 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009860 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009861 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009862 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009863 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009864 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009865 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009866 next;
9867 }
9868
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009869 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009870 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009871 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009872 {
9873 my %Tree = ();
9874 register_TypeUsage($Tid, \%Tree, $LibVersion);
9875
9876 my $Tmpl = 0;
9877 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9878 {
9879 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9880 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9881 {
9882 $Tmpl = 1;
9883 last;
9884 }
9885 }
9886 if(not $Tmpl)
9887 {
9888 foreach (keys(%Tree)) {
9889 $UsedType{$_} = 1;
9890 }
9891 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009892 }
9893 }
9894 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009895
9896 my %Delete = ();
9897
9898 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009899 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009900 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009901 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009902 next;
9903 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009904
9905 if($Kind eq "Extra")
9906 {
9907 my %Tree = ();
9908 register_TypeUsage($Tid, \%Tree, $LibVersion);
9909
9910 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9911 {
9912 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9913 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9914 {
9915 $Delete{$Tid} = 1;
9916 last;
9917 }
9918 }
9919 }
9920 else
9921 {
9922 # remove type
9923 delete($TypeInfo{$LibVersion}{$Tid});
9924 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009925 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009926
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009927 if($Kind eq "Extra")
9928 { # remove duplicates
9929 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9930 {
9931 if($UsedType{$Tid})
9932 { # All & Extended
9933 next;
9934 }
9935
9936 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9937
9938 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9939 delete($TypeInfo{$LibVersion}{$Tid});
9940 }
9941 }
9942 }
9943
9944 foreach my $Tid (keys(%Delete))
9945 {
9946 delete($TypeInfo{$LibVersion}{$Tid});
9947 }
9948}
9949
9950sub check_Completeness($$)
9951{
9952 my ($Info, $LibVersion) = @_;
9953
9954 # data types
9955 if(defined $Info->{"Memb"})
9956 {
9957 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9958 {
9959 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9960 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9961 }
9962 }
9963 }
9964 if(defined $Info->{"Base"})
9965 {
9966 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9967 check_TypeInfo($Bid, $LibVersion);
9968 }
9969 }
9970 if(defined $Info->{"BaseType"}) {
9971 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9972 }
9973 if(defined $Info->{"TParam"})
9974 {
9975 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9976 {
9977 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9978 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9979 next;
9980 }
9981 if($TName eq "_BoolType") {
9982 next;
9983 }
9984 if($TName=~/\Asizeof\(/) {
9985 next;
9986 }
9987 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9988 check_TypeInfo($Tid, $LibVersion);
9989 }
9990 else
9991 {
9992 if(defined $Debug) {
9993 printMsg("WARNING", "missed type $TName");
9994 }
9995 }
9996 }
9997 }
9998
9999 # symbols
10000 if(defined $Info->{"Param"})
10001 {
10002 foreach my $Pos (keys(%{$Info->{"Param"}}))
10003 {
10004 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10005 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10006 }
10007 }
10008 }
10009 if(defined $Info->{"Return"}) {
10010 check_TypeInfo($Info->{"Return"}, $LibVersion);
10011 }
10012 if(defined $Info->{"Class"}) {
10013 check_TypeInfo($Info->{"Class"}, $LibVersion);
10014 }
10015}
10016
10017sub check_TypeInfo($$)
10018{
10019 my ($Tid, $LibVersion) = @_;
10020
10021 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10022 return;
10023 }
10024 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10025
10026 if(defined $TypeInfo{$LibVersion}{$Tid})
10027 {
10028 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10029 printMsg("ERROR", "missed type name ($Tid)");
10030 }
10031 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10032 }
10033 else {
10034 printMsg("ERROR", "missed type id $Tid");
10035 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010036}
10037
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010038sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010039{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010040 my ($TypeId, $LibVersion) = @_;
10041 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010042 if($Type{"Type"} eq "Typedef")
10043 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010044 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010045 if($Base{"Type"}=~/Class|Struct/)
10046 {
10047 if($Type{"Name"} eq $Base{"Name"}) {
10048 return 1;
10049 }
10050 elsif($Type{"Name"}=~/::(\w+)\Z/)
10051 {
10052 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10053 { # QPointer<QWidget>::QPointer
10054 return 1;
10055 }
10056 }
10057 }
10058 }
10059 return 0;
10060}
10061
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010062sub addExtension($)
10063{
10064 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010065 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010066 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010067 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010068 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010069 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10070 $TName=~s/\A(struct|union|class|enum) //;
10071 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010072
10073 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10074 "Header" => "extended.h",
10075 "ShortName" => $Symbol,
10076 "MnglName" => $Symbol,
10077 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10078 );
10079
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010080 $ExtendedSymbols{$Symbol} = 1;
10081 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10082 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010083 }
10084 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010085 $ExtendedSymbols{"external_func_0"} = 1;
10086 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10087 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010088}
10089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010090sub findMethod($$$)
10091{
10092 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010093 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010094 {
10095 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10096 return $VirtMethodInClass;
10097 }
10098 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10099 return $VirtMethodInBaseClasses;
10100 }
10101 }
10102 return "";
10103}
10104
10105sub findMethod_Class($$$)
10106{
10107 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010108 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010109 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10110 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10111 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10112 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10113 { # search for interface with the same parameters suffix (overridden)
10114 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10115 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010116 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10117 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010118 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10119 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010120 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10121 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10122 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10123 return $Candidate;
10124 }
10125 }
10126 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010127 else
10128 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010129 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10130 return $Candidate;
10131 }
10132 }
10133 }
10134 }
10135 return "";
10136}
10137
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010138sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010139{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010140 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010141 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010142 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010143 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10144 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010145 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010146 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010147 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010148 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10149 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010150 { # pure virtual D2-destructors are marked as "virt" in the dump
10151 # virtual D2-destructors are NOT marked as "virt" in the dump
10152 # both destructors are not presented in the v-table
10153 next;
10154 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010155 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010156 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10157 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010158 }
10159}
10160
10161sub registerOverriding($)
10162{
10163 my $LibVersion = $_[0];
10164 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010165 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010166 foreach my $ClassName (@Classes)
10167 {
10168 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10169 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010170 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10171 { # pure virtuals
10172 next;
10173 }
10174 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10175 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010176 {
10177 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10178 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10179 { # both overridden virtual methods
10180 # and implemented pure virtual methods
10181 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10182 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10183 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010185 }
10186 }
10187 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10188 delete($VirtualTable{$LibVersion}{$ClassName});
10189 }
10190 }
10191}
10192
10193sub setVirtFuncPositions($)
10194{
10195 my $LibVersion = $_[0];
10196 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10197 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010198 my ($Num, $Rel) = (1, 0);
10199
10200 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010201 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010202 if($UsedDump{$LibVersion}{"DWARF"}) {
10203 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10204 }
10205 else {
10206 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10207 }
10208 foreach my $VirtFunc (@Funcs)
10209 {
10210 if($UsedDump{$LibVersion}{"DWARF"}) {
10211 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10212 }
10213 else {
10214 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10215 }
10216
10217 # set relative positions
10218 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10219 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10220 { # relative position excluding added and removed virtual functions
10221 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10222 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10223 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10224 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010227 }
10228 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010229 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010230 {
10231 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010232 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010233 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010234 }
10235 }
10236}
10237
10238sub get_sub_classes($$$)
10239{
10240 my ($ClassId, $LibVersion, $Recursive) = @_;
10241 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10242 my @Subs = ();
10243 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10244 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010245 if($Recursive)
10246 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010247 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10248 push(@Subs, $SubSubId);
10249 }
10250 }
10251 push(@Subs, $SubId);
10252 }
10253 return @Subs;
10254}
10255
10256sub get_base_classes($$$)
10257{
10258 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010259 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010260 return () if(not defined $ClassType{"Base"});
10261 my @Bases = ();
10262 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10263 keys(%{$ClassType{"Base"}}))
10264 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010265 if($Recursive)
10266 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010267 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10268 push(@Bases, $SubBaseId);
10269 }
10270 }
10271 push(@Bases, $BaseId);
10272 }
10273 return @Bases;
10274}
10275
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010276sub getVTable_Model($$)
10277{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010278 my ($ClassId, $LibVersion) = @_;
10279 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10280 my @Elements = ();
10281 foreach my $BaseId (@Bases, $ClassId)
10282 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010283 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010284 {
10285 if(defined $VirtualTable{$LibVersion}{$BName})
10286 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010287 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10288 if($UsedDump{$LibVersion}{"DWARF"}) {
10289 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10290 }
10291 else {
10292 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10293 }
10294 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010295 push(@Elements, $VFunc);
10296 }
10297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010298 }
10299 }
10300 return @Elements;
10301}
10302
10303sub getVShift($$)
10304{
10305 my ($ClassId, $LibVersion) = @_;
10306 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10307 my $VShift = 0;
10308 foreach my $BaseId (@Bases)
10309 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010310 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010311 {
10312 if(defined $VirtualTable{$LibVersion}{$BName}) {
10313 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010315 }
10316 }
10317 return $VShift;
10318}
10319
10320sub getShift($$)
10321{
10322 my ($ClassId, $LibVersion) = @_;
10323 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10324 my $Shift = 0;
10325 foreach my $BaseId (@Bases)
10326 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010327 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010328 {
10329 if($Size!=1)
10330 { # not empty base class
10331 $Shift+=$Size;
10332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333 }
10334 }
10335 return $Shift;
10336}
10337
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010338sub getVTable_Size($$)
10339{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010340 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010341 my $Size = 0;
10342 # three approaches
10343 if(not $Size)
10344 { # real size
10345 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10346 $Size = keys(%VTable);
10347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010348 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010349 if(not $Size)
10350 { # shared library symbol size
10351 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10352 $Size /= $WORD_SIZE{$LibVersion};
10353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010354 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010355 if(not $Size)
10356 { # model size
10357 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10358 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10359 }
10360 }
10361 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010362}
10363
10364sub isCopyingClass($$)
10365{
10366 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010367 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010368}
10369
10370sub isLeafClass($$)
10371{
10372 my ($ClassId, $LibVersion) = @_;
10373 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10374}
10375
10376sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010377{ # check structured type for public fields
10378 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010379}
10380
10381sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010382{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010383 my ($TypePtr, $Skip, $Start, $End) = @_;
10384 return 0 if(not $TypePtr);
10385 if($End==-1) {
10386 $End = keys(%{$TypePtr->{"Memb"}})-1;
10387 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010388 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010389 {
10390 if($Skip and $Skip->{$MemPos})
10391 { # skip removed/added fields
10392 next;
10393 }
10394 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10395 {
10396 if(isPublic($TypePtr, $MemPos)) {
10397 return ($MemPos+1);
10398 }
10399 }
10400 }
10401 return 0;
10402}
10403
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010404sub isReserved($)
10405{ # reserved fields == private
10406 my $MName = $_[0];
10407 if($MName=~/reserved|padding|f_spare/i) {
10408 return 1;
10409 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010410 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010411 return 1;
10412 }
10413 if($MName=~/(pad\d+)/i) {
10414 return 1;
10415 }
10416 return 0;
10417}
10418
10419sub isPublic($$)
10420{
10421 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010422
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010423 return 0 if(not $TypePtr);
10424 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10425 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010426
10427 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10428 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010429 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010430 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010431 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010432
10433 # by name in C language
10434 # TODO: add other methods to detect private members
10435 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10436 if($MName=~/priv|abidata|parent_object/i)
10437 { # C-styled private data
10438 return 0;
10439 }
10440 if(lc($MName) eq "abi")
10441 { # ABI information/reserved field
10442 return 0;
10443 }
10444 if(isReserved($MName))
10445 { # reserved fields
10446 return 0;
10447 }
10448
10449 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450}
10451
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010452sub getVTable_Real($$)
10453{
10454 my ($ClassName, $LibVersion) = @_;
10455 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10456 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010457 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010458 if(defined $Type{"VTable"}) {
10459 return %{$Type{"VTable"}};
10460 }
10461 }
10462 return ();
10463}
10464
10465sub cmpVTables($)
10466{
10467 my $ClassName = $_[0];
10468 my $Res = cmpVTables_Real($ClassName, 1);
10469 if($Res==-1) {
10470 $Res = cmpVTables_Model($ClassName);
10471 }
10472 return $Res;
10473}
10474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475sub cmpVTables_Model($)
10476{
10477 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010478 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010479 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010480 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010481 return 1;
10482 }
10483 }
10484 return 0;
10485}
10486
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488{
10489 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10491 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010492 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010493 my %VTable_Old = getVTable_Real($ClassName, 1);
10494 my %VTable_New = getVTable_Real($ClassName, 2);
10495 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010497 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010498 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10501 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010503 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010504 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010506 my $Entry1 = $VTable_Old{$Offset};
10507 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010508 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010509 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010511 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010512
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513 $Entry1 = simpleVEntry($Entry1);
10514 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010515
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010516 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010517 { # NOTE: problem with vtable-dumper
10518 next;
10519 }
10520
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521 if($Entry1 ne $Entry2)
10522 { # register as changed
10523 if($Entry1=~/::([^:]+)\Z/)
10524 {
10525 my $M1 = $1;
10526 if($Entry2=~/::([^:]+)\Z/)
10527 {
10528 my $M2 = $1;
10529 if($M1 eq $M2)
10530 { # overridden
10531 next;
10532 }
10533 }
10534 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010535 if(differentDumps("G"))
10536 {
10537 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10538 {
10539 # GCC 4.6.1: -0x00000000000000010
10540 # GCC 4.7.0: -16
10541 next;
10542 }
10543 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010545 }
10546 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010547 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010548}
10549
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010550sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010551{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010552 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010553 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10554 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010555 my $ClassId = $TName_Tid{1}{$ClassName};
10556 if(isPrivateABI($ClassId, 1)) {
10557 next;
10558 }
10559
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010560 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561 { # already registered
10562 next;
10563 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010566 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 foreach my $Symbol (@Affected)
10568 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010569 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010571 "Target"=>$ClassName);
10572 }
10573 }
10574 }
10575}
10576
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010577sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010579 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010580 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010581 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010582 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010584
10585 if(isPrivateABI($ClassId, 1)) {
10586 next;
10587 }
10588
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010589 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010590 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010591 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010592 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010593 if($TName_Tid{1}{$ClassName}
10594 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010595 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010596 if(defined $CompleteSignature{1}{$Symbol}
10597 and $CompleteSignature{1}{$Symbol}{"Virt"})
10598 { # override some method in v.1
10599 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010600 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010601 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010602 }
10603 }
10604 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010605 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010606 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010607 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010608 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 if($TName_Tid{2}{$ClassName}
10610 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010611 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010612 if(defined $CompleteSignature{2}{$Symbol}
10613 and $CompleteSignature{2}{$Symbol}{"Virt"})
10614 { # override some method in v.2
10615 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010616 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010617 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010618 }
10619 }
10620 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010621 if($Level eq "Binary")
10622 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010623 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010624 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10625 { # check replacements, including pure virtual methods
10626 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10627 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010628 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010629 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10630 if($AddedPos==$RemovedPos)
10631 {
10632 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10633 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10634 last; # other methods will be reported as "added" or "removed"
10635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010636 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010637 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10638 {
10639 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10640 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010641 next;
10642 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010643 my $ProblemType = "Virtual_Replacement";
10644 my @Affected = ($RemovedVFunc);
10645 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10646 { # pure methods
10647 if(not isUsedClass($ClassId, 1, $Level))
10648 { # not a parameter of some exported method
10649 next;
10650 }
10651 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010652
10653 # affected all methods (both virtual and non-virtual ones)
10654 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10655 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010657 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010658 foreach my $AffectedInt (@Affected)
10659 {
10660 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10661 { # affected exported methods only
10662 next;
10663 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010664 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10665 next;
10666 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010667 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10668 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010669 "Target"=>get_Signature($AddedVFunc, 2),
10670 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010672 }
10673 }
10674 }
10675 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010676 if(not checkDump(1, "2.0")
10677 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010678 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010679 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010680 return;
10681 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010682 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010683 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010684 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010685 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010686
10687 if(isPrivateABI($ClassId_Old, 1)) {
10688 next;
10689 }
10690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010691 if(not isCreatable($ClassId_Old, 1))
10692 { # skip classes without public constructors (including auto-generated)
10693 # example: class has only a private exported or private inline constructor
10694 next;
10695 }
10696 if($ClassName=~/>/)
10697 { # skip affected template instances
10698 next;
10699 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010700 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010701 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010702 if(not $ClassId_New) {
10703 next;
10704 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010705 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010706 if($Class_New{"Type"}!~/Class|Struct/)
10707 { # became typedef
10708 if($Level eq "Binary") {
10709 next;
10710 }
10711 if($Level eq "Source")
10712 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010713 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010714 if($Class_New{"Type"}!~/Class|Struct/) {
10715 next;
10716 }
10717 $ClassId_New = $Class_New{"Tid"};
10718 }
10719 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010720
10721 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10722 { # incomplete info in the ABI dump
10723 next;
10724 }
10725
10726
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010727 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10728 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 +040010729
10730 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10731 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10732
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010733 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010734 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10735 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010736 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10737 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010738 my $Shift_Old = getShift($ClassId_Old, 1);
10739 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010740 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010741 my ($Added, $Removed) = (0, 0);
10742 my @StableBases_Old = ();
10743 foreach my $BaseId (@Bases_Old)
10744 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010745 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010746 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010747 push(@StableBases_Old, $BaseId);
10748 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010749 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010750 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010751 { # removed base
10752 # excluding namespace::SomeClass to SomeClass renaming
10753 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010754 if($Level eq "Binary")
10755 { # Binary-level
10756 if($Shift_Old ne $Shift_New)
10757 { # affected fields
10758 if(havePubFields(\%Class_Old)) {
10759 $ProblemKind .= "_And_Shift";
10760 }
10761 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10762 $ProblemKind .= "_And_Size";
10763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010764 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010765 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10766 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010767 { # affected v-table
10768 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010769 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010770 }
10771 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010772 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010773 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10774 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010775 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10776 {
10777 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10778 if($ProblemKind=~/VTable/) {
10779 $VTableChanged_M{$SubName}=1;
10780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010781 }
10782 }
10783 foreach my $Interface (@Affected)
10784 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010785 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10786 next;
10787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010788 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010789 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010790 "Target"=>$BaseName,
10791 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10792 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10793 "Shift"=>abs($Shift_New-$Shift_Old) );
10794 }
10795 $Removed+=1;
10796 }
10797 }
10798 my @StableBases_New = ();
10799 foreach my $BaseId (@Bases_New)
10800 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010801 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010802 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 push(@StableBases_New, $BaseId);
10804 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010805 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010806 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010807 { # added base
10808 # excluding namespace::SomeClass to SomeClass renaming
10809 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010810 if($Level eq "Binary")
10811 { # Binary-level
10812 if($Shift_Old ne $Shift_New)
10813 { # affected fields
10814 if(havePubFields(\%Class_Old)) {
10815 $ProblemKind .= "_And_Shift";
10816 }
10817 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10818 $ProblemKind .= "_And_Size";
10819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010820 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010821 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10822 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010823 { # affected v-table
10824 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010825 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010826 }
10827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010828 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010829 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10830 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010831 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10832 {
10833 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10834 if($ProblemKind=~/VTable/) {
10835 $VTableChanged_M{$SubName}=1;
10836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 }
10838 }
10839 foreach my $Interface (@Affected)
10840 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010841 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10842 next;
10843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010844 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010845 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010846 "Target"=>$BaseName,
10847 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10848 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10849 "Shift"=>abs($Shift_New-$Shift_Old) );
10850 }
10851 $Added+=1;
10852 }
10853 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010854 if($Level eq "Binary")
10855 { # Binary-level
10856 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010857 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10858 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010859 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010860 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010861 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010862 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010863 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010864 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10865 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010866 if($NewPos!=$OldPos)
10867 { # changed position of the base class
10868 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010869 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010870 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10871 next;
10872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010873 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10874 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 "Target"=>$BaseName,
10876 "Old_Value"=>$OldPos-1,
10877 "New_Value"=>$NewPos-1 );
10878 }
10879 }
10880 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10881 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10882 { # became non-virtual base
10883 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10884 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010885 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10886 next;
10887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010888 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10889 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010890 "Target"=>$BaseName );
10891 }
10892 }
10893 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10894 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10895 { # became virtual base
10896 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10897 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010898 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10899 next;
10900 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010901 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10902 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010903 "Target"=>$BaseName );
10904 }
10905 }
10906 }
10907 }
10908 # detect size changes in base classes
10909 if($Shift_Old!=$Shift_New)
10910 { # size of allocable class
10911 foreach my $BaseId (@StableBases_Old)
10912 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010913 my %BaseType = get_Type($BaseId, 1);
10914 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010915 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010916 if($Size_Old ne $Size_New
10917 and $Size_Old and $Size_New)
10918 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010919 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010920 if(isCopyingClass($BaseId, 1)) {
10921 $ProblemType = "Size_Of_Copying_Class";
10922 }
10923 elsif($AllocableClass{1}{$BaseType{"Name"}})
10924 {
10925 if($Size_New>$Size_Old)
10926 { # increased size
10927 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010928 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010929 else
10930 { # decreased size
10931 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10932 if(not havePubFields(\%Class_Old))
10933 { # affected class has no public members
10934 next;
10935 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010936 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010937 }
10938 next if(not $ProblemType);
10939 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10940 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010941 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10942 next;
10943 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010944 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10945 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010946 "Target"=>$BaseType{"Name"},
10947 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10948 "New_Size"=>$Size_New*$BYTE_SIZE );
10949 }
10950 }
10951 }
10952 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010953 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010954 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010955 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010956 { # compare virtual tables size in base classes
10957 my $VShift_Old = getVShift($ClassId_Old, 1);
10958 my $VShift_New = getVShift($ClassId_New, 2);
10959 if($VShift_Old ne $VShift_New)
10960 { # changes in the base class or changes in the list of base classes
10961 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10962 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10963 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010964 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010965 foreach my $BaseId (@AllBases_Old)
10966 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010967 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010968 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010969 { # lost base
10970 next;
10971 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010972 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10973 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 if($VSize_Old!=$VSize_New)
10975 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010976 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010977 { # TODO: affected non-virtual methods?
10978 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010979 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10980 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010981 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010982 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010983 { # skip interfaces that have not changed the absolute virtual position
10984 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010985 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010986 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10987 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010988 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010989 $VTableChanged_M{$BaseType{"Name"}} = 1;
10990 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010991 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10992 { # the reason of the layout change: added virtual functions
10993 next if($VirtualReplacement{$VirtFunc});
10994 my $ProblemType = "Added_Virtual_Method";
10995 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10996 $ProblemType = "Added_Pure_Virtual_Method";
10997 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010998 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010999 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011000 "Target"=>get_Signature($VirtFunc, 2) );
11001 }
11002 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11003 { # the reason of the layout change: removed virtual functions
11004 next if($VirtualReplacement{$VirtFunc});
11005 my $ProblemType = "Removed_Virtual_Method";
11006 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11007 $ProblemType = "Removed_Pure_Virtual_Method";
11008 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011009 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011010 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011011 "Target"=>get_Signature($VirtFunc, 1) );
11012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011013 }
11014 }
11015 }
11016 }
11017 }
11018 }
11019 }
11020}
11021
11022sub isCreatable($$)
11023{
11024 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011025 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011026 or isCopyingClass($ClassId, $LibVersion)) {
11027 return 1;
11028 }
11029 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11030 { # Fix for incomplete data: if this class has
11031 # a base class then it should also has a constructor
11032 return 1;
11033 }
11034 if($ReturnedClass{$LibVersion}{$ClassId})
11035 { # returned by some method of this class
11036 # or any other class
11037 return 1;
11038 }
11039 return 0;
11040}
11041
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011043{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011044 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011045 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11046 { # parameter of some exported method
11047 return 1;
11048 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011049 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11050 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011051 { # method from target class
11052 return 1;
11053 }
11054 return 0;
11055}
11056
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011058{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011059 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011060 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011061 # - virtual
11062 # - pure-virtual
11063 # - non-virtual
11064 if($CompleteSignature{1}{$Interface}{"Data"})
11065 { # global data is not affected
11066 return;
11067 }
11068 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011069 if(not $Class_Id) {
11070 return;
11071 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011072 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011073 if(cmpVTables_Real($CName, 1)==0)
11074 { # no changes
11075 return;
11076 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 $CheckedTypes{$Level}{$CName} = 1;
11078 if($Level eq "Binary")
11079 { # Binary-level
11080 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11081 and not isUsedClass($Class_Id, 1, $Level))
11082 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011083 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011084 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011085 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011086 }
11087 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11088 {
11089 if(defined $VirtualTable{2}{$CName}{$Func}
11090 and defined $CompleteSignature{2}{$Func})
11091 {
11092 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11093 and $CompleteSignature{2}{$Func}{"PureVirt"})
11094 { # became pure virtual
11095 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11096 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011097 "Target"=>get_Signature_M($Func, 1) );
11098 $VTableChanged_M{$CName} = 1;
11099 }
11100 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11101 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11102 { # became non-pure virtual
11103 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11104 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011105 "Target"=>get_Signature_M($Func, 1) );
11106 $VTableChanged_M{$CName} = 1;
11107 }
11108 }
11109 }
11110 if($Level eq "Binary")
11111 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011112 # check virtual table structure
11113 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11114 {
11115 next if($Interface eq $AddedVFunc);
11116 next if($VirtualReplacement{$AddedVFunc});
11117 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11118 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11119 { # pure virtual methods affect all others (virtual and non-virtual)
11120 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011122 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011123 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011124 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011125 elsif(not defined $VirtualTable{1}{$CName}
11126 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011127 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011128 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 { # became polymorphous class, added v-table pointer
11130 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011132 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011133 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011134 }
11135 else
11136 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011137 my $VSize_Old = getVTable_Size($CName, 1);
11138 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011139 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011140 if(isCopyingClass($Class_Id, 1))
11141 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11142 my $ProblemType = "Added_Virtual_Method";
11143 if(isLeafClass($Class_Id, 1)) {
11144 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11145 }
11146 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11147 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011148 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011149 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011151 else
11152 {
11153 my $ProblemType = "Added_Virtual_Method";
11154 if(isLeafClass($Class_Id, 1)) {
11155 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11156 }
11157 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11158 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011159 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011160 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011162 }
11163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011164 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11165 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011166 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011167 if(defined $VirtualTable{1}{$CName}
11168 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011169 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011170 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11171 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011172
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011173 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011174 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011175 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11176 foreach my $ASymbol (@Affected)
11177 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011178 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11179 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011180 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011181 next;
11182 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011183 }
11184 $CheckedSymbols{$Level}{$ASymbol} = 1;
11185 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11186 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011187 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011188 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011191 }
11192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011193 else {
11194 # safe
11195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011197 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11198 {
11199 next if($VirtualReplacement{$RemovedVFunc});
11200 if($RemovedVFunc eq $Interface
11201 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11202 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011203 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011204 next;
11205 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011206 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 { # became non-polymorphous class, removed v-table pointer
11208 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11209 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011210 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011211 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011212 }
11213 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11214 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11215 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011216 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011217 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011218 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11219 next;
11220 }
11221 my $VPos_New = -1;
11222 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011223 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011224 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11225 }
11226 else
11227 {
11228 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011229 next;
11230 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011231 }
11232 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11233 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11234 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11235 {
11236 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11237 foreach my $ASymbol (@Affected)
11238 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011239 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11240 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011241 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011242 next;
11243 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011244 }
11245 my $ProblemType = "Removed_Virtual_Method";
11246 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11247 $ProblemType = "Removed_Pure_Virtual_Method";
11248 }
11249 $CheckedSymbols{$Level}{$ASymbol} = 1;
11250 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11251 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011252 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011253 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011255 }
11256 }
11257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011258 }
11259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011260 else
11261 { # Source-level
11262 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011263 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011264 next if($Interface eq $AddedVFunc);
11265 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011266 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011267 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11268 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011269 "Target"=>get_Signature($AddedVFunc, 2) );
11270 }
11271 }
11272 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11273 {
11274 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11275 {
11276 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11277 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011278 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011279 }
11280 }
11281 }
11282}
11283
11284sub find_MemberPair_Pos_byName($$)
11285{
11286 my ($Member_Name, $Pair_Type) = @_;
11287 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11288 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11289 {
11290 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11291 {
11292 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11293 $Name=~s/\A[_]+|[_]+\Z//g;
11294 if($Name eq $Member_Name) {
11295 return $MemberPair_Pos;
11296 }
11297 }
11298 }
11299 return "lost";
11300}
11301
11302sub find_MemberPair_Pos_byVal($$)
11303{
11304 my ($Member_Value, $Pair_Type) = @_;
11305 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11306 {
11307 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11308 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11309 return $MemberPair_Pos;
11310 }
11311 }
11312 return "lost";
11313}
11314
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011315sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011316{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011317 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011318 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011319 if( $_->{"T1"} eq $_[0]
11320 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011321 {
11322 return 1;
11323 }
11324 }
11325 return 0;
11326}
11327
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011328sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011329{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011330 my %IDs = (
11331 "T1" => $_[0],
11332 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011333 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011334 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011335}
11336
11337sub isRenamed($$$$$)
11338{
11339 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11340 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11341 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011342 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011343 if(not defined $Type2->{"Memb"}{$MemPos}) {
11344 return "";
11345 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011346 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011347 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011348
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011349 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11350 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011351 if($MemberPair_Pos_Rev eq "lost")
11352 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011353 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11354 { # base type match
11355 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011356 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011357 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11358 { # exact type match
11359 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011360 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011361 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11362 { # size match
11363 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011364 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011365 if(isReserved($Pair_Name))
11366 { # reserved fields
11367 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011368 }
11369 }
11370 return "";
11371}
11372
11373sub isLastElem($$)
11374{
11375 my ($Pos, $TypeRef) = @_;
11376 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11377 if($Name=~/last|count|max|total/i)
11378 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11379 return 1;
11380 }
11381 elsif($Name=~/END|NLIMITS\Z/)
11382 { # __RLIMIT_NLIMITS
11383 return 1;
11384 }
11385 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11386 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11387 { # NImageFormats, NColorRoles
11388 return 1;
11389 }
11390 return 0;
11391}
11392
11393sub nonComparable($$)
11394{
11395 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011396
11397 my $N1 = $T1->{"Name"};
11398 my $N2 = $T2->{"Name"};
11399
11400 $N1=~s/\A(struct|union|enum) //;
11401 $N2=~s/\A(struct|union|enum) //;
11402
11403 if($N1 ne $N2
11404 and not isAnon($N1)
11405 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011406 { # different names
11407 if($T1->{"Type"} ne "Pointer"
11408 or $T2->{"Type"} ne "Pointer")
11409 { # compare base types
11410 return 1;
11411 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011412 if($N1!~/\Avoid\s*\*/
11413 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011414 {
11415 return 1;
11416 }
11417 }
11418 elsif($T1->{"Type"} ne $T2->{"Type"})
11419 { # different types
11420 if($T1->{"Type"} eq "Class"
11421 and $T2->{"Type"} eq "Struct")
11422 { # "class" to "struct"
11423 return 0;
11424 }
11425 elsif($T2->{"Type"} eq "Class"
11426 and $T1->{"Type"} eq "Struct")
11427 { # "struct" to "class"
11428 return 0;
11429 }
11430 else
11431 { # "class" to "enum"
11432 # "union" to "class"
11433 # ...
11434 return 1;
11435 }
11436 }
11437 return 0;
11438}
11439
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011440sub isOpaque($)
11441{
11442 my $T = $_[0];
11443 if(not defined $T->{"Memb"})
11444 {
11445 return 1;
11446 }
11447 return 0;
11448}
11449
11450sub removeVPtr($)
11451{ # support for old ABI dumps
11452 my $TPtr = $_[0];
11453 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11454 if($#Pos>=1)
11455 {
11456 foreach my $Pos (0 .. $#Pos-1)
11457 {
11458 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11459 }
11460 delete($TPtr->{"Memb"}{$#Pos});
11461 }
11462}
11463
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011464sub isPrivateABI($$)
11465{
11466 my ($TypeId, $LibVersion) = @_;
11467
11468 if($CheckPrivateABI) {
11469 return 0;
11470 }
11471
11472 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11473 return 1;
11474 }
11475
11476 return 0;
11477}
11478
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011479sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011480{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011481 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011482 return {} if(not $Type1_Id or not $Type2_Id);
11483
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011484 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011485 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011486 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011487 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011488
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011489 my %Type1 = get_Type($Type1_Id, 1);
11490 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011491 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011492 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011493 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011494
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011495 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11496 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011497
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011498 if(defined $UsedDump{1}{"DWARF"})
11499 {
11500 if($Type1_Pure{"Name"} eq "__unknown__"
11501 or $Type2_Pure{"Name"} eq "__unknown__")
11502 { # Error ABI dump
11503 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11504 }
11505 }
11506
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011507 if(isPrivateABI($Type1_Id, 1)) {
11508 return {};
11509 }
11510
11511 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11512 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11513
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011514 my %SubProblems = ();
11515
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011516 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11517 {
11518 if($Type1_Pure{"Type"}=~/Struct|Union/
11519 and $Type2_Pure{"Type"}=~/Struct|Union/)
11520 {
11521 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11522 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011523 if(not defined $UsedDump{1}{"DWARF"}
11524 and not defined $UsedDump{2}{"DWARF"})
11525 {
11526 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11527 "Target"=>$Type1_Pure{"Name"},
11528 "Type_Name"=>$Type1_Pure{"Name"} );
11529 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011530
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011531 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011532 }
11533 }
11534 }
11535
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011536 if(not $Type1_Pure{"Size"}
11537 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011538 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011539 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11540 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11541 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011542 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011543 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011544 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011545 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011546 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011547 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011548 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011549 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11550 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11551 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011552
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011553 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11554 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011555 }
11556
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011557 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11558 { # support for old ABI dumps
11559 # _vptr field added in 3.0
11560 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11561 {
11562 if(defined $Type2_Pure{"Memb"}
11563 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11564 {
11565 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11566 delete($Type2_Pure{"Memb"}{0});
11567 }
11568 else {
11569 removeVPtr(\%Type2_Pure);
11570 }
11571 }
11572 }
11573 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11574 {
11575 if(defined $Type1_Pure{"Memb"}
11576 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11577 {
11578 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11579 delete($Type1_Pure{"Memb"}{0});
11580 }
11581 else {
11582 removeVPtr(\%Type1_Pure);
11583 }
11584 }
11585 }
11586 }
11587
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011588 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11589 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011590
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011591 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011592 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11593 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011594 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011595 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11596 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011597 if($Base_1{"Name"} ne $Base_2{"Name"})
11598 {
11599 if(differentDumps("G")
11600 or differentDumps("V"))
11601 { # different GCC versions or different dumps
11602 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11603 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11604 # std::__va_list and __va_list
11605 $Base_1{"Name"}=~s/\A(\w+::)+//;
11606 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011607 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11608 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011610 }
11611 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11612 and $Base_1{"Name"} ne $Base_2{"Name"})
11613 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011614 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011615 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011616 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011617 {
11618 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11619 "Target"=>$Typedef_1{"Name"},
11620 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011621 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11622 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11623 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011624 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11625 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011626
11627 if(defined $UsedDump{1}{"DWARF"})
11628 {
11629 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11630 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11631 { # Error ABI dump
11632 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11633 }
11634 }
11635
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011636 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011637 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011638 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11639 {
11640 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11641 "Target"=>$Typedef_1{"Name"},
11642 "Type_Name"=>$Typedef_1{"Name"},
11643 "Old_Value"=>$Base_1{"Name"},
11644 "New_Value"=>$Base_2{"Name"} );
11645 }
11646 else
11647 {
11648 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11649 "Target"=>$Typedef_1{"Name"},
11650 "Type_Name"=>$Typedef_1{"Name"},
11651 "Old_Value"=>$Base_1{"Name"},
11652 "New_Value"=>$Base_2{"Name"} );
11653 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011655 }
11656 }
11657 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11658 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011659 my $TT1 = $Type1_Pure{"Type"};
11660 my $TT2 = $Type2_Pure{"Type"};
11661
11662 if($TT1 ne $TT2
11663 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011664 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011665 my $Short1 = $Type1_Pure{"Name"};
11666 my $Short2 = $Type2_Pure{"Name"};
11667
11668 $Short1=~s/\A\Q$TT1\E //ig;
11669 $Short2=~s/\A\Q$TT2\E //ig;
11670
11671 if($Short1 eq $Short2)
11672 {
11673 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11674 "Target"=>$Type1_Pure{"Name"},
11675 "Type_Name"=>$Type1_Pure{"Name"},
11676 "Old_Value"=>lc($Type1_Pure{"Type"}),
11677 "New_Value"=>lc($Type2_Pure{"Type"}) );
11678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011679 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011680 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011681 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011682
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011683 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011684
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011685 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11686 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11687 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11688 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011689 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011690 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011691 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011692 {
11693 my $ProblemKind = "DataType_Size";
11694 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011695 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011696 {
11697 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11698 $ProblemKind = "Size_Of_Copying_Class";
11699 }
11700 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11701 {
11702 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11703 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11704 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011705 else
11706 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011707 # descreased size of allocable class
11708 # it has no special effects
11709 }
11710 }
11711 }
11712 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11713 "Target"=>$Type1_Pure{"Name"},
11714 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011715 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011716 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011717 }
11718 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011719 if(defined $Type1_Pure{"BaseType"}
11720 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011721 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011722 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11723 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011724 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011725 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11726 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011727 }
11728 }
11729 }
11730 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11731 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11732 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11733 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11734 { # detect removed and renamed fields
11735 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11736 next if(not $Member_Name);
11737 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);
11738 if($MemberPair_Pos eq "lost")
11739 {
11740 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11741 {
11742 if(isUnnamed($Member_Name))
11743 { # support for old-version dumps
11744 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011745 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011746 next;
11747 }
11748 }
11749 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11750 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011751 $RenamedField{$Member_Pos} = $RenamedTo;
11752 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011753 }
11754 else
11755 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011756 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011757 }
11758 }
11759 elsif($Type1_Pure{"Type"} eq "Enum")
11760 {
11761 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11762 next if($Member_Value1 eq "");
11763 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11764 if($MemberPair_Pos ne "lost")
11765 { # renamed
11766 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11767 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11768 if($MemberPair_Pos_Rev eq "lost")
11769 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011770 $RenamedField{$Member_Pos} = $RenamedTo;
11771 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 }
11773 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011774 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011775 }
11776 }
11777 else
11778 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011779 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011780 }
11781 }
11782 }
11783 else
11784 { # related
11785 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11786 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11787 }
11788 }
11789 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11790 { # detect added fields
11791 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11792 next if(not $Member_Name);
11793 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);
11794 if($MemberPair_Pos eq "lost")
11795 {
11796 if(isUnnamed($Member_Name))
11797 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011798 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011799 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011800 next;
11801 }
11802 }
11803 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11804 {
11805 if(not $RenamedField_Rev{$Member_Pos})
11806 { # added
11807 $AddedField{$Member_Pos}=1;
11808 }
11809 }
11810 }
11811 }
11812 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11813 { # detect moved fields
11814 my (%RelPos, %RelPosName, %AbsPos) = ();
11815 my $Pos = 0;
11816 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11817 { # relative positions in 1st version
11818 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11819 next if(not $Member_Name);
11820 if(not $RemovedField{$Member_Pos})
11821 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011822 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011823 $RelPosName{1}{$Pos} = $Member_Name;
11824 $AbsPos{1}{$Pos++} = $Member_Pos;
11825 }
11826 }
11827 $Pos = 0;
11828 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11829 { # relative positions in 2nd version
11830 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11831 next if(not $Member_Name);
11832 if(not $AddedField{$Member_Pos})
11833 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011834 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011835 $RelPosName{2}{$Pos} = $Member_Name;
11836 $AbsPos{2}{$Pos++} = $Member_Pos;
11837 }
11838 }
11839 foreach my $Member_Name (keys(%{$RelPos{1}}))
11840 {
11841 my $RPos1 = $RelPos{1}{$Member_Name};
11842 my $AbsPos1 = $NameToPosA{$Member_Name};
11843 my $Member_Name2 = $Member_Name;
11844 if(my $RenamedTo = $RenamedField{$AbsPos1})
11845 { # renamed
11846 $Member_Name2 = $RenamedTo;
11847 }
11848 my $RPos2 = $RelPos{2}{$Member_Name2};
11849 if($RPos2 ne "" and $RPos1 ne $RPos2)
11850 { # different relative positions
11851 my $AbsPos2 = $NameToPosB{$Member_Name2};
11852 if($AbsPos1 ne $AbsPos2)
11853 { # different absolute positions
11854 my $ProblemType = "Moved_Field";
11855 if(not isPublic(\%Type1_Pure, $AbsPos1))
11856 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011857 if($Level eq "Source") {
11858 next;
11859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011860 $ProblemType = "Moved_Private_Field";
11861 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011862 if($Level eq "Binary"
11863 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011864 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011865 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011866 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011867 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011868 if($MemSize1 ne $MemSize2) {
11869 $ProblemType .= "_And_Size";
11870 }
11871 }
11872 if($ProblemType eq "Moved_Private_Field") {
11873 next;
11874 }
11875 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11876 "Target"=>$Member_Name,
11877 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011878 "Old_Value"=>$RPos1,
11879 "New_Value"=>$RPos2 );
11880 }
11881 }
11882 }
11883 }
11884 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011885 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011886 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11887 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011888 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011889 if(my $RenamedTo = $RenamedField{$Member_Pos})
11890 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011891 if(defined $Constants{2}{$Member_Name})
11892 {
11893 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11894 { # define OLD NEW
11895 next; # Safe
11896 }
11897 }
11898
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011899 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11900 {
11901 if(isPublic(\%Type1_Pure, $Member_Pos))
11902 {
11903 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11904 "Target"=>$Member_Name,
11905 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011906 "Old_Value"=>$Member_Name,
11907 "New_Value"=>$RenamedTo );
11908 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011909 elsif(isReserved($Member_Name))
11910 {
11911 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11912 "Target"=>$Member_Name,
11913 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011914 "Old_Value"=>$Member_Name,
11915 "New_Value"=>$RenamedTo );
11916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011917 }
11918 elsif($Type1_Pure{"Type"} eq "Enum")
11919 {
11920 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11921 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11922 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011923 "Old_Value"=>$Member_Name,
11924 "New_Value"=>$RenamedTo );
11925 }
11926 }
11927 elsif($RemovedField{$Member_Pos})
11928 { # removed
11929 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11930 {
11931 my $ProblemType = "Removed_Field";
11932 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011933 or isUnnamed($Member_Name))
11934 {
11935 if($Level eq "Source") {
11936 next;
11937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011938 $ProblemType = "Removed_Private_Field";
11939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011940 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011941 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011942 {
11943 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11944 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011945 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 +040011946 { # changed offset
11947 $ProblemType .= "_And_Layout";
11948 }
11949 }
11950 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11951 { # affected size
11952 $ProblemType .= "_And_Size";
11953 }
11954 }
11955 if($ProblemType eq "Removed_Private_Field") {
11956 next;
11957 }
11958 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11959 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011960 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011961 }
11962 elsif($Type2_Pure{"Type"} eq "Union")
11963 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011964 if($Level eq "Binary"
11965 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011966 {
11967 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11968 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011969 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011970 }
11971 else
11972 {
11973 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11974 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011975 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 }
11977 }
11978 elsif($Type1_Pure{"Type"} eq "Enum")
11979 {
11980 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11981 "Target"=>$Member_Name,
11982 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983 "Old_Value"=>$Member_Name );
11984 }
11985 }
11986 else
11987 { # changed
11988 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11989 if($Type1_Pure{"Type"} eq "Enum")
11990 {
11991 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11992 next if($Member_Value1 eq "");
11993 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11994 next if($Member_Value2 eq "");
11995 if($Member_Value1 ne $Member_Value2)
11996 {
11997 my $ProblemType = "Enum_Member_Value";
11998 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11999 $ProblemType = "Enum_Last_Member_Value";
12000 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012001 if($SkipConstants{1}{$Member_Name}) {
12002 $ProblemType = "Enum_Private_Member_Value";
12003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12005 "Target"=>$Member_Name,
12006 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012007 "Old_Value"=>$Member_Value1,
12008 "New_Value"=>$Member_Value2 );
12009 }
12010 }
12011 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12012 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012013 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12014 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12015
12016 if($Access1 ne "private"
12017 and $Access2 eq "private")
12018 {
12019 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12020 "Target"=>$Member_Name,
12021 "Type_Name"=>$Type1_Pure{"Name"});
12022 }
12023 elsif($Access1 ne "protected"
12024 and $Access1 ne "private"
12025 and $Access2 eq "protected")
12026 {
12027 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12028 "Target"=>$Member_Name,
12029 "Type_Name"=>$Type1_Pure{"Name"});
12030 }
12031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012032 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12033 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012034 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012035 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12036 $SizeV1 = $BSize1;
12037 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012038 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012039 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12040 $SizeV2 = $BSize2;
12041 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012042 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12043 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012044 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012045 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012046 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012047 {
12048 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12049 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12050 { # field size change (including anon-structures and unions)
12051 # - same types
12052 # - unnamed types
12053 # - bitfields
12054 my $ProblemType = "Field_Size";
12055 if(not isPublic(\%Type1_Pure, $Member_Pos)
12056 or isUnnamed($Member_Name))
12057 { # should not be accessed by applications, goes to "Low Severity"
12058 # example: "abidata" members in GStreamer types
12059 $ProblemType = "Private_".$ProblemType;
12060 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012061 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 +040012062 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012063 if($Type2_Pure{"Type"} ne "Union"
12064 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012065 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012066 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 +040012067 { # changed offset
12068 $ProblemType .= "_And_Layout";
12069 }
12070 }
12071 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12072 $ProblemType .= "_And_Type_Size";
12073 }
12074 }
12075 if($ProblemType eq "Private_Field_Size")
12076 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012077 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012078 if($ProblemType eq "Field_Size")
12079 {
12080 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12081 { # Low severity
12082 $ProblemType = "Struct_Field_Size_Increased";
12083 }
12084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 if($ProblemType)
12086 { # register a problem
12087 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12088 "Target"=>$Member_Name,
12089 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012090 "Old_Size"=>$SizeV1,
12091 "New_Size"=>$SizeV2);
12092 }
12093 }
12094 }
12095 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12096 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12097 { # do NOT check bitfield type changes
12098 next;
12099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012100 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012101 {
12102 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12103 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12104 {
12105 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12106 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012107 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012108 }
12109 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12110 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12111 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012112 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012113 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012114 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012115 }
12116 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012117 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12118 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012120 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12121 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012122
12123 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012124 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012125 or $ProblemType eq "Field_Type_And_Size"
12126 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012127 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012128 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012129 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012130 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012131 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012132 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012133 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012134 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012135 }
12136 }
12137 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12138 {
12139 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012140 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012141 }
12142 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012143 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012144 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012145 }
12146 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12147 {
12148 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012149 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012150 }
12151 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012152 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012153 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012154 }
12155 }
12156 }
12157
12158 if($Level eq "Source")
12159 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012160 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012161 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012162 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12163 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012164
12165 if($ProblemType eq "Field_Type")
12166 {
12167 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012168 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012169 }
12170 }
12171 }
12172 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012173
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012174 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012175 {
12176 my $ProblemType_Init = $ProblemType;
12177 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012178 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012179 if(not isPublic(\%Type1_Pure, $Member_Pos)
12180 or isUnnamed($Member_Name)) {
12181 $ProblemType = "Private_".$ProblemType;
12182 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012183 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 +040012184 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012185 if($Type2_Pure{"Type"} ne "Union"
12186 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012187 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012188 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 +040012189 { # changed offset
12190 $ProblemType .= "_And_Layout";
12191 }
12192 }
12193 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12194 $ProblemType .= "_And_Type_Size";
12195 }
12196 }
12197 }
12198 else
12199 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012200 # TODO: Private_Field_Type rule?
12201
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012202 if(not isPublic(\%Type1_Pure, $Member_Pos)
12203 or isUnnamed($Member_Name)) {
12204 next;
12205 }
12206 }
12207 if($ProblemType eq "Private_Field_Type_And_Size")
12208 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012209 }
12210 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12211 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012212 "Type_Name"=>$Type1_Pure{"Name"});
12213
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012214 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012216 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012217 }
12218 }
12219 if(not isPublic(\%Type1_Pure, $Member_Pos))
12220 { # do NOT check internal type changes
12221 next;
12222 }
12223 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012224 { # checking member type changes
12225 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12226
12227 my %DupProblems = ();
12228
12229 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012230 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012231 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012232 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012233 if(not defined $AllAffected)
12234 {
12235 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12236 next;
12237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012238 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012239
12240 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12241 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12242
12243 if(not defined $AllAffected)
12244 {
12245 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012246 }
12247 }
12248 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012249
12250 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012251 }
12252 }
12253 }
12254 }
12255 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12256 { # checking added members, public and private
12257 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12258 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012259 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260 if($AddedField{$Member_Pos})
12261 { # added
12262 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12263 {
12264 my $ProblemType = "Added_Field";
12265 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012266 or isUnnamed($Member_Name))
12267 {
12268 if($Level eq "Source") {
12269 next;
12270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 $ProblemType = "Added_Private_Field";
12272 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012273 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012274 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 {
12276 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12277 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012278 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 +040012279 { # changed offset
12280 $ProblemType .= "_And_Layout";
12281 }
12282 }
12283 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12284 $ProblemType .= "_And_Size";
12285 }
12286 }
12287 if($ProblemType eq "Added_Private_Field")
12288 { # skip added private fields
12289 next;
12290 }
12291 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12292 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012293 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012294 }
12295 elsif($Type2_Pure{"Type"} eq "Union")
12296 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012297 if($Level eq "Binary"
12298 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012299 {
12300 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12301 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012302 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012303 }
12304 else
12305 {
12306 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12307 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012308 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309 }
12310 }
12311 elsif($Type2_Pure{"Type"} eq "Enum")
12312 {
12313 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12314 next if($Member_Value eq "");
12315 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12316 "Target"=>$Member_Name,
12317 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012318 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012319 }
12320 }
12321 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012322
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012323 if($Type1_Pure{"Type"} eq "FuncPtr")
12324 {
12325 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12326 {
12327 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12328 next;
12329 }
12330
12331 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12332 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12333
12334 my $PName = "p".$PPos;
12335
12336 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12337 my %DupProblems = ();
12338
12339 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12340 {
12341 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12342 {
12343 if(not defined $AllAffected)
12344 {
12345 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12346 next;
12347 }
12348 }
12349
12350 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12351 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12352
12353 if(not defined $AllAffected)
12354 {
12355 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12356 }
12357 }
12358 }
12359
12360 %DupProblems = ();
12361 }
12362 }
12363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012364 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012365 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012366}
12367
12368sub isUnnamed($) {
12369 return $_[0]=~/\Aunnamed\d+\Z/;
12370}
12371
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012372sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012373{
12374 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012375 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12376 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12377 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012379 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012380 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012381 }
12382 return $TypeName;
12383}
12384
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012385sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012388 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12390 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012391 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012392 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12393 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394 return () if(not $Type{"Type"});
12395 if($Type{"Type"} ne $Type_Type)
12396 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012397 return () if(not $Type{"BaseType"});
12398 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012400 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012401 return %Type;
12402}
12403
12404my %TypeSpecAttributes = (
12405 "Const" => 1,
12406 "Volatile" => 1,
12407 "ConstVolatile" => 1,
12408 "Restrict" => 1,
12409 "Typedef" => 1
12410);
12411
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012412sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012413{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012414 my ($TypeId, $Info) = @_;
12415 if(not $TypeId or not $Info
12416 or not $Info->{$TypeId}) {
12417 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012418 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012419 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12420 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12421 }
12422 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012423 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012424 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012425 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012426 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012427 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012428 return %Type;
12429}
12430
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012431sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012432{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012433 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012434 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012435 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12436 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012437 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012438 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12439 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012440 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12441 my $PLevel = 0;
12442 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12443 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012444 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012445 return $PLevel if(not $Type{"BaseType"});
12446 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12447 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12448 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449}
12450
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012451sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012453 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012454 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012455 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12456 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012457 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012458 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12459 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012460 return %Type if(not $Type{"BaseType"});
12461 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012462 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012463 return %Type;
12464}
12465
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012467{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012468 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012469 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012470 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12471 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012472 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012473 my $Qual = "";
12474 if($Type{"Type"} eq "Pointer") {
12475 $Qual .= "*";
12476 }
12477 elsif($Type{"Type"} eq "Ref") {
12478 $Qual .= "&";
12479 }
12480 elsif($Type{"Type"} eq "ConstVolatile") {
12481 $Qual .= "const volatile";
12482 }
12483 elsif($Type{"Type"} eq "Const"
12484 or $Type{"Type"} eq "Volatile"
12485 or $Type{"Type"} eq "Restrict") {
12486 $Qual .= lc($Type{"Type"});
12487 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012488 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012489 return $BQual.$Qual;
12490}
12491
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012492sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012493{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012494 my ($TypeId, $Info) = @_;
12495 if(not $TypeId or not $Info
12496 or not $Info->{$TypeId}) {
12497 return ();
12498 }
12499 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012500 return %Type if(not $Type{"BaseType"});
12501 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012502 {
12503 if($Info->{$BTid}) {
12504 return %{$Info->{$BTid}};
12505 }
12506 else { # something is going wrong
12507 return ();
12508 }
12509 }
12510 else {
12511 return %Type;
12512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513}
12514
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012515sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012516{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012517 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012518 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012519 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12520 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521}
12522
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012523sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012524{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012525 my $Symbol = $_[0];
12526 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12527}
12528
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012529sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012530 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12531}
12532
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012533sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012534{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012535 my ($SInfo, $LibVersion) = @_;
12536
12537 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012538 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012539 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012540 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012541 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012542 return 1;
12543 }
12544 }
12545 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012546 if(my $ShortName = $SInfo->{"ShortName"})
12547 {
12548 if(index($ShortName,"<")!=-1
12549 and index($ShortName,">")!=-1) {
12550 return 1;
12551 }
12552 }
12553
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012554 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555}
12556
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012557sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012558{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012559 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012560 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012561 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012562 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012563 { # class specialization
12564 return 1;
12565 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012566 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012567 { # method specialization
12568 return 1;
12569 }
12570 }
12571 return 0;
12572}
12573
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012574sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012576 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012577
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012578 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 { # non-public global data
12580 return 0;
12581 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012582
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012583 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012584 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012585 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012586 }
12587
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012588 if($Symbol=~/\A_Z/)
12589 {
12590 if($Symbol=~/[CD][3-4]E/) {
12591 return 0;
12592 }
12593 }
12594
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012595 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012596 { # support for old ABI dumps in --headers-only mode
12597 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12598 {
12599 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12600 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012601 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 if(not $PType or $PType eq "Unknown") {
12603 return 0;
12604 }
12605 }
12606 }
12607 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012608 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012610 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12611
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012612 if($SkipSymbols{$LibVersion}{$Symbol})
12613 { # user defined symbols to ignore
12614 return 0;
12615 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012616
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012617 if($SymbolsListPath and not $SymbolsList{$Symbol})
12618 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012619 if(not $TargetHeadersPath or not $Header
12620 or not is_target_header($Header, 1))
12621 { # -symbols-list | -headers-list
12622 return 0;
12623 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012624 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012625
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012626 if($AppPath and not $SymbolsList_App{$Symbol})
12627 { # user defined symbols (in application)
12628 return 0;
12629 }
12630
12631 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12632
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012633 if($ClassId)
12634 {
12635 if(not isTargetType($ClassId, $LibVersion)) {
12636 return 0;
12637 }
12638 }
12639
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12641 if(not $NameSpace and $ClassId)
12642 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012643 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012644 }
12645 if($NameSpace)
12646 { # user defined namespaces to ignore
12647 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12648 return 0;
12649 }
12650 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12651 { # nested namespaces
12652 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12653 return 0;
12654 }
12655 }
12656 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012657 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012658 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012659 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012660 { # --skip-headers or <skip_headers> (not <skip_including>)
12661 if($Skip==1) {
12662 return 0;
12663 }
12664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012665 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012666 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012667 { # user defined types
12668 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12669
12670 if(not $TypesList{$CName})
12671 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012672 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12673 {
12674 $CName=~s/\A\Q$NS\E\:\://g;
12675 }
12676
12677 if(not $TypesList{$CName})
12678 {
12679 my $Found = 0;
12680
12681 while($CName=~s/\:\:.+?\Z//)
12682 {
12683 if($TypesList{$CName})
12684 {
12685 $Found = 1;
12686 last;
12687 }
12688 }
12689
12690 if(not $Found) {
12691 return 0;
12692 }
12693 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012694 }
12695 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012696
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012697 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12698 { # non-target symbols
12699 return 0;
12700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012701 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012702 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012703 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12704 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012705 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012706 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12707 { # inline virtual methods
12708 if($Type=~/InlineVirt/) {
12709 return 1;
12710 }
12711 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12712 if(not $Allocable)
12713 { # check bases
12714 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12715 {
12716 if(not isCopyingClass($DCId, $LibVersion))
12717 { # exists a derived class without default c-tor
12718 $Allocable=1;
12719 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012721 }
12722 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012723 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012724 return 0;
12725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012726 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012727 else
12728 { # inline non-virtual methods
12729 return 0;
12730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012732 }
12733 }
12734 return 1;
12735}
12736
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012737sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012738{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012739 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012740 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12741 {
12742 if(link_symbol($Symbol, 1, "+Deps"))
12743 { # linker can find a new symbol
12744 # in the old-version library
12745 # So, it's not a new symbol
12746 next;
12747 }
12748 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012749 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012750 next;
12751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012752 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012753 }
12754}
12755
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012756sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012757{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012758 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012759 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12760 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012761 if(link_symbol($Symbol, 2, "+Deps"))
12762 { # linker can find an old symbol
12763 # in the new-version library
12764 next;
12765 }
12766 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012767 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 next;
12769 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012770 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012771 }
12772}
12773
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012775{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012776 my $Level = $_[0];
12777 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012778 { # checking added symbols
12779 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012780 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012781 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012782 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012783 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012784 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012785 { # checking removed symbols
12786 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012787 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012788 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 { # skip v-tables for templates, that should not be imported by applications
12790 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012791 if(my $CName = $VTableClass{$Symbol})
12792 {
12793 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12794 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012795 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012796 next;
12797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012799
12800 if($SkipSymbols{1}{$Symbol})
12801 { # user defined symbols to ignore
12802 next;
12803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012804 }
12805 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012806 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012807 }
12808 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12809 { # symbols for pure virtual methods cannot be called by clients
12810 next;
12811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 }
12814}
12815
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012816sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012817{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012818 my ($LibVersion, $V) = @_;
12819 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12820 return $Cache{"checkDump"}{$LibVersion}{$V};
12821 }
12822 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012823}
12824
12825sub detectAdded_H($)
12826{
12827 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012828 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12829 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012830 if($Level eq "Source")
12831 { # remove symbol version
12832 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12833 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012834
12835 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12836 { # skip artificial constructors
12837 next;
12838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012840 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12841 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012842 next;
12843 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012844 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012845 next;
12846 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012847 if(not defined $CompleteSignature{1}{$Symbol}
12848 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12849 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012850 if($UsedDump{2}{"SrcBin"})
12851 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012852 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012853 { # support for old and different (!) ABI dumps
12854 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12855 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012856 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012857 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012858 {
12859 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12860 {
12861 if($Lang eq "C")
12862 { # support for old ABI dumps: missed extern "C" functions
12863 next;
12864 }
12865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012866 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012867 else
12868 {
12869 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012870 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012871 next;
12872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012873 }
12874 }
12875 }
12876 }
12877 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878 }
12879 }
12880}
12881
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012882sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012883{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012884 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012885 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12886 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012887 if($Level eq "Source")
12888 { # remove symbol version
12889 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12890 $Symbol=$SN;
12891 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012892 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12893 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012894 next;
12895 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012896 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012897 next;
12898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012899 if(not defined $CompleteSignature{2}{$Symbol}
12900 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012901 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012902 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012904 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012905 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012906 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12907 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012908 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012909 if($CheckHeadersOnly)
12910 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012911 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12912 {
12913 if($Lang eq "C")
12914 { # support for old ABI dumps: missed extern "C" functions
12915 next;
12916 }
12917 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012918 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012919 else
12920 {
12921 if(not link_symbol($Symbol, 1, "-Deps"))
12922 { # skip removed inline symbols
12923 next;
12924 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012925 }
12926 }
12927 }
12928 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012929 if(not checkDump(1, "2.15"))
12930 {
12931 if($Symbol=~/_IT_E\Z/)
12932 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12933 next;
12934 }
12935 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012936 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12937 {
12938 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12939 {
12940 if(defined $Constants{2}{$Short})
12941 {
12942 my $Val = $Constants{2}{$Short}{"Value"};
12943 if(defined $Func_ShortName{2}{$Val})
12944 { # old name defined to new
12945 next;
12946 }
12947 }
12948 }
12949
12950 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012951 $RemovedInt{$Level}{$Symbol} = 1;
12952 if($Level eq "Source")
12953 { # search for a source-compatible equivalent
12954 setAlternative($Symbol, $Level);
12955 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012956 }
12957 }
12958}
12959
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012961{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012962 my $Level = $_[0];
12963 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012964 { # checking added symbols
12965 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012966 next if($CompleteSignature{2}{$Symbol}{"Private"});
12967 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012968 if($Level eq "Binary")
12969 {
12970 if($CompleteSignature{2}{$Symbol}{"InLine"})
12971 {
12972 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12973 { # skip inline non-virtual functions
12974 next;
12975 }
12976 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012977 }
12978 else
12979 { # Source
12980 if($SourceAlternative_B{$Symbol}) {
12981 next;
12982 }
12983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012986 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012987 { # checking removed symbols
12988 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012989 next if($CompleteSignature{1}{$Symbol}{"Private"});
12990 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012991 if($Level eq "Binary")
12992 {
12993 if($CompleteSignature{1}{$Symbol}{"InLine"})
12994 {
12995 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12996 { # skip inline non-virtual functions
12997 next;
12998 }
12999 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013000 }
13001 else
13002 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013003 if(my $Alt = $SourceAlternative{$Symbol})
13004 {
13005 if(defined $CompleteSignature{1}{$Alt}
13006 and $CompleteSignature{1}{$Symbol}{"Const"})
13007 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013008 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013009 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013010 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013011 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013012 }
13013 else
13014 { # do NOT show removed symbol
13015 next;
13016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013017 }
13018 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013019 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013020 }
13021}
13022
13023sub addParamNames($)
13024{
13025 my $LibraryVersion = $_[0];
13026 return if(not keys(%AddIntParams));
13027 my $SecondVersion = $LibraryVersion==1?2:1;
13028 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13029 {
13030 next if(not keys(%{$AddIntParams{$Interface}}));
13031 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013032 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013033 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13034 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013035 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013036 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13037 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13038 {
13039 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13040 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13041 }
13042 }
13043 else {
13044 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13045 }
13046 }
13047 }
13048 }
13049}
13050
13051sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013052{ # detect changed typedefs to show
13053 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013054 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13055 {
13056 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013057 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13058 if(not $BName1 or isAnon($BName1)) {
13059 next;
13060 }
13061 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13062 if(not $BName2 or isAnon($BName2)) {
13063 next;
13064 }
13065 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013066 $ChangedTypedef{$Typedef} = 1;
13067 }
13068 }
13069}
13070
13071sub get_symbol_suffix($$)
13072{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013073 my ($Symbol, $Full) = @_;
13074 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013075 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013076 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013077 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013078 if(not $Full) {
13079 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13080 }
13081 return $Suffix;
13082}
13083
13084sub get_symbol_prefix($$)
13085{
13086 my ($Symbol, $LibVersion) = @_;
13087 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13088 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13089 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013090 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013091 }
13092 return $ShortName;
13093}
13094
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013095sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013096{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013097 my $Symbol = $_[0];
13098 my $PSymbol = $Symbol;
13099 if(not defined $CompleteSignature{2}{$PSymbol}
13100 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13101 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13102 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013103 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013104 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013105 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013106 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013107 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13108 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013109 {
13110 if(defined $CompleteSignature{2}{$PSymbol}
13111 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13112 {
13113 $SourceAlternative{$Symbol} = $PSymbol;
13114 $SourceAlternative_B{$PSymbol} = $Symbol;
13115 if(not defined $CompleteSignature{1}{$PSymbol}
13116 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13117 $SourceReplacement{$Symbol} = $PSymbol;
13118 }
13119 }
13120 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013121 }
13122 else
13123 {
13124 foreach my $Sp ("KV", "VK", "K", "V")
13125 {
13126 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13127 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13128 {
13129 if(defined $CompleteSignature{2}{$PSymbol}
13130 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13131 {
13132 $SourceAlternative{$Symbol} = $PSymbol;
13133 $SourceAlternative_B{$PSymbol} = $Symbol;
13134 if(not defined $CompleteSignature{1}{$PSymbol}
13135 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13136 $SourceReplacement{$Symbol} = $PSymbol;
13137 }
13138 }
13139 }
13140 $PSymbol = $Symbol;
13141 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013142 }
13143 }
13144 }
13145 return "";
13146}
13147
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013148sub getSymKind($$)
13149{
13150 my ($Symbol, $LibVersion) = @_;
13151 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13152 {
13153 return "Global_Data";
13154 }
13155 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13156 {
13157 return "Method";
13158 }
13159 return "Function";
13160}
13161
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013162sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013163{
13164 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013165 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013166
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013167 mergeBases($Level);
13168
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013169 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013171 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013172 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013173 next;
13174 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013175 if(defined $CompleteSignature{1}{$Symbol}
13176 and $CompleteSignature{1}{$Symbol}{"Header"})
13177 { # double-check added symbol
13178 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013179 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013180 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181 next;
13182 }
13183 if($Symbol=~/\A(_Z|\?)/)
13184 { # C++
13185 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13186 }
13187 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13188 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013189 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13190 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013191 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013192 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013193 {
13194 if($TName_Tid{1}{$AffectedClass_Name})
13195 { # class should exist in previous version
13196 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13197 { # old v-table is NOT copied by old applications
13198 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13199 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013200 "Target"=>get_Signature($Symbol, 2),
13201 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013202 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013205 }
13206 }
13207 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013208 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13209 { # check all removed exported symbols
13210 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013211 next;
13212 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013213 if(defined $CompleteSignature{2}{$Symbol}
13214 and $CompleteSignature{2}{$Symbol}{"Header"})
13215 { # double-check removed symbol
13216 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013217 }
13218 if($CompleteSignature{1}{$Symbol}{"Private"})
13219 { # skip private methods
13220 next;
13221 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013222 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013223 next;
13224 }
13225 $CheckedSymbols{$Level}{$Symbol} = 1;
13226 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13227 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013228 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13229 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013230 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013231 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13232 {
13233 if($TName_Tid{2}{$AffectedClass_Name})
13234 { # class should exist in newer version
13235 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13236 { # old v-table is NOT copied by old applications
13237 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13238 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013239 "Target"=>get_Signature($OverriddenMethod, 1),
13240 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013241 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013244 }
13245 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013246 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013247 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013248 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013249 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013250 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013251 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013253 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013254 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013255 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013256 {
13257 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13258 "Target"=>$tr_name{$Symbol},
13259 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013260 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013262 else
13263 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013264 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013265 "Target"=>$tr_name{$Symbol},
13266 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013267 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013268 }
13269 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013270 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013272 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013273 {
13274 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13275 "Target"=>$tr_name{$Symbol},
13276 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013277 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013279 else
13280 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013281 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013282 "Target"=>$tr_name{$Symbol},
13283 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013284 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013285 }
13286 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013287 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13288 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13289 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13290 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13291 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013292 {
13293 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013295 $ProblemType = "Global_Data_Symbol_Changed_Type";
13296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013297 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13298 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013299 "Old_Type"=>$RTName1,
13300 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013301 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013302 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 }
13304 }
13305 }
13306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013307 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013308 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013309 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013310 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013311 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013312 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013313 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013314 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13315 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013316 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013317 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013318 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013319 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 }
13321 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013322 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13323 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013324 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013325 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013327 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013328 }
13329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013330 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013331 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013332 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013333 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013335 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013336 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013337 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013338 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013339 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013340 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013341 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013342 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013343 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013344 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013345 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013346 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013347 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013350 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013351 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013352 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013353 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013354 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 { # "volatile" to non-"volatile"
13356
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013357 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013359 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013360 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013361 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013362 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013363 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013364 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013365 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013366 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013367 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013368 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013370 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013371 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013372 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013374 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13375 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013376 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013377 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013378 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 }
13380 }
13381 }
13382 }
13383 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013384 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13385 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013386 $CurrentSymbol = $Symbol;
13387
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013388 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13389 if($Level eq "Source")
13390 { # remove symbol version
13391 $Symbol=$SN;
13392 }
13393 else
13394 { # Binary
13395 if(not $SV)
13396 { # symbol without version
13397 if(my $VSym = $SymVer{1}{$Symbol})
13398 { # the symbol is linked with versioned symbol
13399 if($CompleteSignature{2}{$VSym}{"MnglName"})
13400 { # show report for symbol@ver only
13401 next;
13402 }
13403 elsif(not link_symbol($VSym, 2, "-Deps"))
13404 { # changed version: sym@v1 to sym@v2
13405 # do NOT show report for symbol
13406 next;
13407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 }
13409 }
13410 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013411 my $PSymbol = $Symbol;
13412 if($Level eq "Source"
13413 and my $S = $SourceReplacement{$Symbol})
13414 { # take a source-compatible replacement function
13415 $PSymbol = $S;
13416 }
13417 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 { # private symbols
13419 next;
13420 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 if(not defined $CompleteSignature{1}{$Symbol}
13422 or not defined $CompleteSignature{2}{$PSymbol})
13423 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 next;
13425 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013426 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13427 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13428 { # no mangled name
13429 next;
13430 }
13431 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13432 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 { # without a header
13434 next;
13435 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013436
13437 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13438 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13439 { # became pure
13440 next;
13441 }
13442 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13443 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13444 { # became non-pure
13445 next;
13446 }
13447
13448 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13449 { # exported, target, inline virtual and pure virtual
13450 next;
13451 }
13452 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13453 { # exported, target, inline virtual and pure virtual
13454 next;
13455 }
13456
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013457 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013458 {
13459 if($CompleteSignature{1}{$Symbol}{"Data"}
13460 and $CompleteSignature{2}{$PSymbol}{"Data"})
13461 {
13462 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13463 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13464 if(defined $Value1)
13465 {
13466 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13467 if(defined $Value2)
13468 {
13469 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13470 if($Value1 ne $Value2)
13471 {
13472 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13473 "Old_Value"=>$Value1,
13474 "New_Value"=>$Value2,
13475 "Target"=>get_Signature($Symbol, 1) );
13476 }
13477 }
13478 }
13479 }
13480 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013481
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013482 if($CompleteSignature{2}{$PSymbol}{"Private"})
13483 {
13484 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13485 "Target"=>get_Signature_M($PSymbol, 2) );
13486 }
13487 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13488 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13489 {
13490 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13491 "Target"=>get_Signature_M($PSymbol, 2) );
13492 }
13493 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13494 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13495 {
13496 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13497 "Target"=>get_Signature_M($PSymbol, 2) );
13498 }
13499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013500 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013501 mergeVirtualTables($Symbol, $Level);
13502
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013503 if($COMPILE_ERRORS)
13504 { # if some errors occurred at the compiling stage
13505 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013506 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013507 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013508 { # missed information about parameters in newer version
13509 next;
13510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013511 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013512 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013513 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013514 next;
13515 }
13516 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013517 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013518 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013519 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013520 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13521 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013522 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13523 "Target"=>get_Signature($Symbol, 1)
13524 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013525 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013526 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013527 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13528 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013529 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 "Target"=>get_Signature($Symbol, 1)
13531 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013532 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013533 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13534 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013535 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013536 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013537 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013538 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13539 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13540 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013541 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013542 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013543 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13544 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013545 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013546 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013547 my $ProblemType = "Virtual_Method_Position";
13548 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13549 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013550 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013551 if(isUsedClass($Class_Id, 1, $Level))
13552 {
13553 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013554 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013555 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013556 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13557 next;
13558 }
13559 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013560 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013561 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13562 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013563 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013564 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013565 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013567 }
13568 }
13569 }
13570 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013571 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13572 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013573 { # do NOT check type changes in pure virtuals
13574 next;
13575 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013576 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 if($Symbol=~/\A(_Z|\?)/
13578 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013580 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013581 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013582 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013583 }
13584 }
13585 else
13586 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013587 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013588 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013589 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013590 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13591 last if($PType2_Name eq "...");
13592 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13593 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013594 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013595 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013597 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13598 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013599 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13600 $ParamPos_Prev = "lost";
13601 }
13602 }
13603 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013604 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 }
13606 if($ParamPos_Prev eq "lost")
13607 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013608 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013609 {
13610 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013611 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013612 $ProblemType = "Added_Unnamed_Parameter";
13613 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013614 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013615 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013616 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013617 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013618 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013619 }
13620 else
13621 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013622 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013623 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013624 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013625 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13626 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013627 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013628 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013629 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013630 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013631 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013632 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013633 "Param_Type"=>$PType2_Name,
13634 "Old_Value"=>$PName_Old,
13635 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013636 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013637 }
13638 }
13639 else
13640 {
13641 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013642 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013643 $ProblemType = "Added_Middle_Unnamed_Parameter";
13644 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013645 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013646 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013647 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013648 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013649 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013650 }
13651 }
13652 }
13653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013656 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013658 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013659 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013660 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013661 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013662 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013663 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13664 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013665 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 }
13667 }
13668 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013669 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013670 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013671 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013672 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13673 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013674 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13675 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013677 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013679 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13680 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013681 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13682 $ParamPos_New = "lost";
13683 }
13684 }
13685 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013686 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013687 }
13688 if($ParamPos_New eq "lost")
13689 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013690 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013691 {
13692 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013693 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013694 $ProblemType = "Removed_Unnamed_Parameter";
13695 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013696 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013697 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013698 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013699 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013700 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013701 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013702 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013703 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013704 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013705 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013706 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013707 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013708 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013710 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013711 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013712 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013713 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013714 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013715 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013716 "Old_Value"=>$PName,
13717 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013718 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013719 }
13720 }
13721 else
13722 {
13723 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013724 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013725 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13726 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013727 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013728 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013729 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013730 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013731 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013732 }
13733 }
13734 }
13735 }
13736 }
13737 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013738 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13739 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013740 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013741
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013742 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013743 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013744 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13745 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013746 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013747
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013748 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013749 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013750 if($SubProblemType eq "Return_Type_And_Size") {
13751 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13752 }
13753 elsif($SubProblemType eq "Return_Type_Format") {
13754 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13755 }
13756 else {
13757 $ProblemTypes{"Global_Data_Type"} = 1;
13758 }
13759
13760 # quals
13761 if($SubProblemType eq "Return_Type"
13762 or $SubProblemType eq "Return_Type_And_Size"
13763 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013764 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013765 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13766 { # const to non-const
13767 if($RR==2) {
13768 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13769 }
13770 else {
13771 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13772 }
13773 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013774 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013775 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13776 { # non-const to const
13777 if($RA==2) {
13778 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13779 }
13780 else {
13781 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13782 }
13783 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013784 }
13785 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013786 }
13787 else
13788 {
13789 # quals
13790 if($SubProblemType eq "Return_Type"
13791 or $SubProblemType eq "Return_Type_And_Size"
13792 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013793 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013794 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013795 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013796 if(addedQual($Old_Value, $New_Value, "volatile"))
13797 {
13798 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13799 if($Level ne "Source"
13800 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13801 $ProblemTypes{"Return_Type"} = 1;
13802 }
13803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013804 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013805 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13806 {
13807 if($RA==2) {
13808 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13809 }
13810 else {
13811 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13812 }
13813 if($Level ne "Source"
13814 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13815 $ProblemTypes{"Return_Type"} = 1;
13816 }
13817 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013818 }
13819 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013820 if($Level eq "Binary"
13821 and not $CompleteSignature{1}{$Symbol}{"Data"})
13822 {
13823 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13824 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13825 { # if one of the architectures is unknown
13826 # then set other arhitecture to unknown too
13827 ($Arch1, $Arch2) = ("unknown", "unknown");
13828 }
13829 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013830 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013831 {
13832 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13833 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13834 }
13835 else
13836 {
13837 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13838 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13839 }
13840
13841 if($SubProblemType eq "Return_Type_Became_Void")
13842 {
13843 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13844 { # parameters stack has been affected
13845 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013847 }
13848 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013849 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013850 }
13851 }
13852 }
13853 elsif($SubProblemType eq "Return_Type_From_Void")
13854 {
13855 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13856 { # parameters stack has been affected
13857 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013859 }
13860 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013861 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013862 }
13863 }
13864 }
13865 elsif($SubProblemType eq "Return_Type"
13866 or $SubProblemType eq "Return_Type_And_Size"
13867 or $SubProblemType eq "Return_Type_Format")
13868 {
13869 if($Conv1{"Method"} ne $Conv2{"Method"})
13870 {
13871 if($Conv1{"Method"} eq "stack")
13872 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013873 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013874 }
13875 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013876 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013877 }
13878 }
13879 else
13880 {
13881 if($Conv1{"Method"} eq "reg")
13882 {
13883 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13884 {
13885 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013886 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013887 }
13888 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013889 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013890 }
13891 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013892 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013893 }
13894 }
13895 }
13896 }
13897 }
13898 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013899
13900 if(not keys(%ProblemTypes))
13901 { # default
13902 $ProblemTypes{$SubProblemType} = 1;
13903 }
13904
13905 foreach my $ProblemType (keys(%ProblemTypes))
13906 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013907 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013908 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013909 }
13910 if($ReturnType1_Id and $ReturnType2_Id)
13911 {
13912 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013913 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13914
13915 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013916
13917 if($CompleteSignature{1}{$Symbol}{"Data"})
13918 {
13919 if($Level eq "Binary")
13920 {
13921 if(get_PLevel($ReturnType1_Id, 1)==0)
13922 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013923 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013924 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013925
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013926 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13927 {
13928 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013929 {
13930 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13931 {
13932 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13933 last;
13934 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013935 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013936 }
13937 }
13938 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013939 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013940 {
13941 if(defined $GlobalDataObject{1}{$Symbol}
13942 and defined $GlobalDataObject{2}{$Symbol})
13943 {
13944 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13945 my $New_Size = $GlobalDataObject{2}{$Symbol};
13946 if($Old_Size!=$New_Size)
13947 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013948 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013949 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013950 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013951 }
13952 }
13953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013954 }
13955 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013956
13957 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013958 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013959 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013960 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013961 my $NewLocation = "retval";
13962 if($SubLocation and $SubLocation ne "retval") {
13963 $NewLocation = "retval->".$SubLocation;
13964 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013965 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13966 }
13967 }
13968
13969 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13970 {
13971 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13972 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013973 my $NewLocation = "retval";
13974 if($SubLocation and $SubLocation ne "retval") {
13975 $NewLocation = "retval->".$SubLocation;
13976 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013977 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013978 }
13979 }
13980 }
13981
13982 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013983 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13984 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13985 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013986 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013987 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013988 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13989 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013990 if($ThisPtr1_Id and $ThisPtr2_Id)
13991 {
13992 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013993 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13994 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013995 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013996 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013997 {
13998 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013999 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014000 }
14001 }
14002 }
14003 }
14004 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014005 if($Level eq "Binary") {
14006 mergeVTables($Level);
14007 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014008 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14009 $CheckedSymbols{$Level}{$Symbol} = 1;
14010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014011}
14012
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014013sub rmQuals($$)
14014{
14015 my ($Value, $Qual) = @_;
14016 if(not $Qual) {
14017 return $Value;
14018 }
14019 if($Qual eq "all")
14020 { # all quals
14021 $Qual = "const|volatile|restrict";
14022 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014023 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014024 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014025 }
14026 return $Value;
14027}
14028
14029sub cmpBTypes($$$$)
14030{
14031 my ($T1, $T2, $V1, $V2) = @_;
14032 $T1 = uncover_typedefs($T1, $V1);
14033 $T2 = uncover_typedefs($T2, $V2);
14034 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14035}
14036
14037sub addedQual($$$)
14038{
14039 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014040 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014041}
14042
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014043sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014044{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014045 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014046 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014047}
14048
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014049sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014050{
14051 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14052 $Old_Value = uncover_typedefs($Old_Value, $V1);
14053 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014054
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014055 if($Old_Value eq $New_Value)
14056 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014057 return 0;
14058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014059 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014060 { # without a qual
14061 return 0;
14062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014063 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014064 { # became non-qual
14065 return 1;
14066 }
14067 else
14068 {
14069 my @BQ1 = getQualModel($Old_Value, $Qual);
14070 my @BQ2 = getQualModel($New_Value, $Qual);
14071 foreach (0 .. $#BQ1)
14072 { # removed qual
14073 if($BQ1[$_]==1
14074 and $BQ2[$_]!=1)
14075 {
14076 return 2;
14077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014078 }
14079 }
14080 return 0;
14081}
14082
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014083sub getQualModel($$)
14084{
14085 my ($Value, $Qual) = @_;
14086 if(not $Qual) {
14087 return $Value;
14088 }
14089
14090 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014091 while($Value=~/(\w+)/)
14092 {
14093 my $W = $1;
14094
14095 if($W eq $Qual) {
14096 $Value=~s/\b$W\b/\@/g;
14097 }
14098 else {
14099 $Value=~s/\b$W\b//g;
14100 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014101 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014102
14103 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014104 $Value=~s/[^\*\&\w]+//g;
14105
14106 # modeling
14107 # int*const*const == 011
14108 # int**const == 001
14109 my @Model = ();
14110 my @Elems = split(/[\*\&]/, $Value);
14111 if(not @Elems) {
14112 return (0);
14113 }
14114 foreach (@Elems)
14115 {
14116 if($_ eq $Qual) {
14117 push(@Model, 1);
14118 }
14119 else {
14120 push(@Model, 0);
14121 }
14122 }
14123
14124 return @Model;
14125}
14126
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014127my %StringTypes = map {$_=>1} (
14128 "char*",
14129 "char const*"
14130);
14131
14132my %CharTypes = map {$_=>1} (
14133 "char",
14134 "char const"
14135);
14136
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014137sub showVal($$$)
14138{
14139 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014140 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014141 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014142 if(substr($Value, 0, 2) eq "_Z")
14143 {
14144 if(my $Unmangled = $tr_name{$Value}) {
14145 return $Unmangled;
14146 }
14147 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014148 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014149 { # strings
14150 return "\"$Value\"";
14151 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014152 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014153 { # characters
14154 return "\'$Value\'";
14155 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014156 if($Value eq "")
14157 { # other
14158 return "\'\'";
14159 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014160 return $Value;
14161}
14162
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014163sub getRegs($$$)
14164{
14165 my ($LibVersion, $Symbol, $Pos) = @_;
14166
14167 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14168 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014169 my %Regs = ();
14170 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14171 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014172 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014173 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14174 }
14175 }
14176
14177 return join(", ", sort keys(%Regs));
14178 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014179 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14180 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14181 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14182 {
14183 return "unknown";
14184 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014185
14186 return undef;
14187}
14188
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014189sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014190{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014191 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014192 if(not $Symbol) {
14193 return;
14194 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014195 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14196 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14197 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14198 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014199 if(not $PType1_Id
14200 or not $PType2_Id) {
14201 return;
14202 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014203
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014204 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014205 { # do not merge "this"
14206 if($PName1 eq "this" or $PName2 eq "this") {
14207 return;
14208 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014209 }
14210
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014211 my %Type1 = get_Type($PType1_Id, 1);
14212 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014213
14214 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14215
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014216 my %BaseType1 = get_BaseType($PType1_Id, 1);
14217 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014218
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014219 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014220
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014221 if($Level eq "Binary")
14222 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014223 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014224 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14225 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14226 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14227 {
14228 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014229 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014230 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014231 }
14232 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14233 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14234 {
14235 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014236 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014237 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014239 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014240
14241 if(defined $UsedDump{1}{"DWARF"}
14242 and defined $UsedDump{2}{"DWARF"})
14243 {
14244 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14245 {
14246 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14247 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014248
14249 if($Old_Regs ne "unknown"
14250 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014251 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014252 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014253 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014254 if($Old_Regs ne $New_Regs)
14255 {
14256 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14257 "Target"=>$PName1,
14258 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14259 "Old_Value"=>$Old_Regs,
14260 "New_Value"=>$New_Regs );
14261 }
14262 }
14263 elsif($Old_Regs and not $New_Regs)
14264 {
14265 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014266 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014267 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014268 "Old_Value"=>$Old_Regs );
14269 }
14270 elsif(not $Old_Regs and $New_Regs)
14271 {
14272 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14273 "Target"=>$PName1,
14274 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014275 "New_Value"=>$New_Regs );
14276 }
14277 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014278
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014279 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14280 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14281 {
14282 if($Old_Offset ne $New_Offset)
14283 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014284 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14285 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14286
14287 $Old_Offset = $Old_Offset - $Start1;
14288 $New_Offset = $New_Offset - $Start2;
14289
14290 if($Old_Offset ne $New_Offset)
14291 {
14292 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14293 "Target"=>$PName1,
14294 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14295 "Old_Value"=>$Old_Offset,
14296 "New_Value"=>$New_Offset );
14297 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014298 }
14299 }
14300 }
14301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014303 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14304 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014305 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014306 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014307 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14308 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014309 if(not checkDump(1, "2.13")
14310 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014311 { # support for old ABI dumps
14312 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014313 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014314 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014315 and $Value_Old eq "false" and $Value_New eq "0")
14316 { # int class::method ( bool p = 0 );
14317 # old ABI dumps: "false"
14318 # new ABI dumps: "0"
14319 $Value_Old = "0";
14320 }
14321 }
14322 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014323 if(not checkDump(1, "2.18")
14324 and checkDump(2, "2.18"))
14325 { # support for old ABI dumps
14326 if(not defined $Value_Old
14327 and substr($Value_New, 0, 2) eq "_Z") {
14328 $Value_Old = $Value_New;
14329 }
14330 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014331 if(defined $Value_Old)
14332 {
14333 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14334 if(defined $Value_New)
14335 {
14336 $Value_New = showVal($Value_New, $PType2_Id, 2);
14337 if($Value_Old ne $Value_New)
14338 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014339 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014340 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014341 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014342 "Old_Value"=>$Value_Old,
14343 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014344 }
14345 }
14346 else
14347 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014348 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014349 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014350 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014351 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014352 }
14353 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014354 elsif(defined $Value_New)
14355 {
14356 $Value_New = showVal($Value_New, $PType2_Id, 2);
14357 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14358 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014359 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014360 "New_Value"=>$Value_New );
14361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014362 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014363
14364 if($ChkRnmd)
14365 {
14366 if($PName1 and $PName2 and $PName1 ne $PName2
14367 and $PType1_Id!=-1 and $PType2_Id!=-1
14368 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14369 { # except unnamed "..." value list (Id=-1)
14370 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14371 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014372 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014373 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14374 "Old_Value"=>$PName1,
14375 "New_Value"=>$PName2,
14376 "New_Signature"=>get_Signature($Symbol, 2) );
14377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014378 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014380 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014381 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014382
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014383 foreach my $SubProblemType (keys(%SubProblems))
14384 { # add new problems, remove false alarms
14385 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14386 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014387
14388 # quals
14389 if($SubProblemType eq "Parameter_Type"
14390 or $SubProblemType eq "Parameter_Type_And_Size"
14391 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014392 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014393 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014394 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014395 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014396 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014397 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014398 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14399 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14400 }
14401 }
14402 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14403 {
14404 if(removedQual($Old_Value, $New_Value, "volatile")) {
14405 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014406 }
14407 }
14408 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14409 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14410 { # int to "int const"
14411 delete($SubProblems{$SubProblemType});
14412 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014413 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14415 { # "int const" to int
14416 delete($SubProblems{$SubProblemType});
14417 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014418 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14419 { # "const" to non-"const"
14420 if($RR==2) {
14421 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14422 }
14423 else {
14424 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14425 }
14426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014427 }
14428 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014429
14430 if($Level eq "Source")
14431 {
14432 foreach my $SubProblemType (keys(%SubProblems))
14433 {
14434 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14435 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14436
14437 if($SubProblemType eq "Parameter_Type")
14438 {
14439 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14440 delete($SubProblems{$SubProblemType});
14441 }
14442 }
14443 }
14444 }
14445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014446 foreach my $SubProblemType (keys(%SubProblems))
14447 { # modify/register problems
14448 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14449 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014450 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14451 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014453 my $NewProblemType = $SubProblemType;
14454 if($Old_Value eq "..." and $New_Value ne "...")
14455 { # change from "..." to "int"
14456 if($ParamPos1==0)
14457 { # ISO C requires a named argument before "..."
14458 next;
14459 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014460 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014461 }
14462 elsif($New_Value eq "..." and $Old_Value ne "...")
14463 { # change from "int" to "..."
14464 if($ParamPos2==0)
14465 { # ISO C requires a named argument before "..."
14466 next;
14467 }
14468 $NewProblemType = "Parameter_Became_VaList";
14469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014470 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014471 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014472 {
14473 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014474 if($Arch1 eq "unknown"
14475 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014477 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014478 ($Arch1, $Arch2) = ("unknown", "unknown");
14479 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014480 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014481 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014482 { # real
14483 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14484 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14485 }
14486 else
14487 { # model
14488 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14489 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14490 }
14491 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014492 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014493 if($Conv1{"Method"} eq "stack")
14494 {
14495 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14496 $NewProblemType = "Parameter_Type_And_Stack";
14497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014498 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014499 elsif($Conv1{"Method"} eq "reg")
14500 {
14501 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14502 $NewProblemType = "Parameter_Type_And_Register";
14503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014504 }
14505 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014506 elsif($Conv1{"Method"} ne "unknown"
14507 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014509 if($Conv1{"Method"} eq "stack") {
14510 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014511 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014512 elsif($Conv1{"Method"} eq "register") {
14513 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014514 }
14515 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014516 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14517 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014518 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014519 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014520 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014521 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014522 "New_Signature"=>get_Signature($Symbol, 2) );
14523 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014524 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014525
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014528 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014529 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14530 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014531 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014532 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 {
14534 my $NewProblemType = $SubProblemType;
14535 if($SubProblemType eq "DataType_Size")
14536 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014537 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538 { # stack has been affected
14539 $NewProblemType = "DataType_Size_And_Stack";
14540 }
14541 }
14542 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014543 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014544 }
14545 }
14546}
14547
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014548sub find_ParamPair_Pos_byName($$$)
14549{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014550 my ($Name, $Symbol, $LibVersion) = @_;
14551 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014553 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14554 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555 {
14556 return $ParamPos;
14557 }
14558 }
14559 return "lost";
14560}
14561
14562sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14563{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014564 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014565 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014566 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014567 {
14568 next if($Order eq "backward" and $ParamPos>$MediumPos);
14569 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014570 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14571 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014572 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573 push(@Positions, $ParamPos);
14574 }
14575 }
14576 return @Positions;
14577}
14578
14579sub getTypeIdByName($$)
14580{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014581 my ($TypeName, $LibVersion) = @_;
14582 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014583}
14584
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014585sub diffTypes($$$)
14586{
14587 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14588 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14589 }
14590 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14591 { # skip recursive declarations
14592 return 0;
14593 }
14594
14595 pushType($_[0], $_[1], \@RecurTypes_Diff);
14596 my $Diff = diffTypes_I(@_);
14597 pop(@RecurTypes_Diff);
14598
14599 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14600}
14601
14602sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014603{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014604 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014605
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014606 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14607 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014609 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14610 { # equal types
14611 return 0;
14612 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014613 if($Type1_Pure{"Name"} eq "void")
14614 { # from void* to something
14615 return 0;
14616 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014617 if($Type1_Pure{"Name"}=~/\*/
14618 or $Type2_Pure{"Name"}=~/\*/)
14619 { # compared in detectTypeChange()
14620 return 0;
14621 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014623 my %FloatType = map {$_=>1} (
14624 "float",
14625 "double",
14626 "long double"
14627 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014628
14629 my $T1 = $Type1_Pure{"Type"};
14630 my $T2 = $Type2_Pure{"Type"};
14631
14632 if($T1 eq "Struct"
14633 and $T2 eq "Class")
14634 { # compare as data structures
14635 $T2 = "Struct";
14636 }
14637
14638 if($T1 eq "Class"
14639 and $T2 eq "Struct")
14640 { # compare as data structures
14641 $T1 = "Struct";
14642 }
14643
14644 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014646 if($T1 eq "Intrinsic"
14647 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014648 { # "int" to "enum"
14649 return 0;
14650 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014651 elsif($T2 eq "Intrinsic"
14652 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014653 { # "enum" to "int"
14654 return 0;
14655 }
14656 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014657 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014658 # ...
14659 return 1;
14660 }
14661 }
14662 else
14663 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014664 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014665 {
14666 if($FloatType{$Type1_Pure{"Name"}}
14667 or $FloatType{$Type2_Pure{"Name"}})
14668 { # "float" to "double"
14669 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014670 if($Level eq "Source")
14671 { # Safe
14672 return 0;
14673 }
14674 else {
14675 return 1;
14676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014677 }
14678 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014679 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014680 {
14681 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14682 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014683 if(not @Membs1
14684 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014685 { # private
14686 return 0;
14687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014688 if($#Membs1!=$#Membs2)
14689 { # different number of elements
14690 return 1;
14691 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014692 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014693 {
14694 foreach my $Pos (@Membs1)
14695 { # compare elements by name and value
14696 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14697 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14698 { # different names
14699 return 1;
14700 }
14701 }
14702 }
14703 else
14704 {
14705 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014706 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014707 if($Level eq "Source")
14708 {
14709 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14710 { # different names
14711 return 1;
14712 }
14713 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014714
14715 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14716 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14717
14718 if($MT1{"Name"} ne $MT2{"Name"}
14719 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14720 {
14721 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14722 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14723
14724 if($PL1 ne $PL2)
14725 { # different pointer level
14726 return 1;
14727 }
14728
14729 # compare base types
14730 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14731 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14732
14733 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14734 { # different types
14735 return 1;
14736 }
14737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014738 }
14739 }
14740 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014741 else
14742 {
14743 # TODO: arrays, etc.
14744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 }
14746 return 0;
14747}
14748
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014749sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014750{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014751 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014752 if(not $Type1_Id or not $Type2_Id) {
14753 return ();
14754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014755 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014756 my %Type1 = get_Type($Type1_Id, 1);
14757 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014758 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14759 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014760
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014761 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14762 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 +040014763
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014764 if(defined $UsedDump{1}{"DWARF"})
14765 {
14766 if($Type1_Pure{"Name"} eq "__unknown__"
14767 or $Type2_Pure{"Name"} eq "__unknown__"
14768 or $Type1_Base{"Name"} eq "__unknown__"
14769 or $Type2_Base{"Name"} eq "__unknown__")
14770 { # Error ABI dump
14771 return ();
14772 }
14773 }
14774
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014775 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14776 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014777 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14778 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14779 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14780 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14781 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14782 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14783 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014784 if($Type1{"Name"} eq $Type2{"Name"})
14785 {
14786 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14787 { # will be reported in mergeTypes() as typedef problem
14788 return ();
14789 }
14790 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14791 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14792 if(%Typedef_1 and %Typedef_2)
14793 {
14794 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14795 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14796 { # const Typedef
14797 return ();
14798 }
14799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014800 }
14801 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14802 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014803 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014804 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14805 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014806 {
14807 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14808 "Old_Value"=>$Type1_Base{"Name"},
14809 "New_Value"=>$Type2_Base{"Name"},
14810 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014811 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014812 }
14813 else
14814 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014815 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014816 { # format change
14817 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14818 "Old_Value"=>$Type1_Base{"Name"},
14819 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014820 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014821 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822 }
14823 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14824 {
14825 %{$LocalProblems{$Prefix."_BaseType"}}=(
14826 "Old_Value"=>$Type1_Base{"Name"},
14827 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014828 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014829 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014830 }
14831 }
14832 }
14833 }
14834 elsif($Type1{"Name"} ne $Type2{"Name"})
14835 { # type change
14836 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14837 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014838 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014839 and $Type1_Pure{"Name"} eq "void")
14840 {
14841 %{$LocalProblems{"Return_Type_From_Void"}}=(
14842 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014843 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014845 elsif($Prefix eq "Return"
14846 and $Type2_Pure{"Name"} eq "void")
14847 {
14848 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14849 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014850 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014852 else
14853 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014854 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014855 and $Type1{"Size"} and $Type2{"Size"}
14856 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014857 {
14858 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14859 "Old_Value"=>$Type1{"Name"},
14860 "New_Value"=>$Type2{"Name"},
14861 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014862 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014863 }
14864 else
14865 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014866 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014867 { # format change
14868 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14869 "Old_Value"=>$Type1{"Name"},
14870 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014871 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014872 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014873 }
14874 elsif(tNameLock($Type1_Id, $Type2_Id))
14875 { # FIXME: correct this condition
14876 %{$LocalProblems{$Prefix."_Type"}}=(
14877 "Old_Value"=>$Type1{"Name"},
14878 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014879 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014880 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014881 }
14882 }
14883 }
14884 }
14885 }
14886 if($Type1_PLevel!=$Type2_PLevel)
14887 {
14888 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14889 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014891 if($Level eq "Source")
14892 {
14893 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014894 "Old_Value"=>$Type1_PLevel,
14895 "New_Value"=>$Type2_PLevel);
14896 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014897 else
14898 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014899 if($Type2_PLevel>$Type1_PLevel)
14900 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014901 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14902 "Old_Value"=>$Type1_PLevel,
14903 "New_Value"=>$Type2_PLevel);
14904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014905 else
14906 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014907 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14908 "Old_Value"=>$Type1_PLevel,
14909 "New_Value"=>$Type2_PLevel);
14910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014911 }
14912 }
14913 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014914 if($Type1_Pure{"Type"} eq "Array"
14915 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014916 { # base_type[N] -> base_type[N]
14917 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014918 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014919 foreach my $SubProblemType (keys(%SubProblems))
14920 {
14921 $SubProblemType=~s/_Type/_BaseType/g;
14922 next if(defined $LocalProblems{$SubProblemType});
14923 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14924 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14925 }
14926 }
14927 }
14928 return %LocalProblems;
14929}
14930
14931sub tNameLock($$)
14932{
14933 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014934 my $Changed = 0;
14935 if(differentDumps("G"))
14936 { # different GCC versions
14937 $Changed = 1;
14938 }
14939 elsif(differentDumps("V"))
14940 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014941 if(not checkDump(1, "2.20")
14942 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014943 { # latest names update
14944 # 2.6: added restrict qualifier
14945 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014946 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014947 $Changed = 1;
14948 }
14949 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014950
14951 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14952 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14953
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014954 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14955 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14956
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014957 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014958 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014959 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014960 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014961 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014963 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014964 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014965 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014966 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014967 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14968 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14969 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014970 { # equal base types
14971 return 0;
14972 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014973
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014974 if(not checkDump(1, "2.13")
14975 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014976 { # broken array names in ABI dumps < 2.13
14977 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014978 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 return 0;
14980 }
14981 }
14982
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014983 if(not checkDump(1, "2.6")
14984 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014985 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014986 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014987 and $TN2=~/\brestrict\b/) {
14988 return 0;
14989 }
14990 }
14991
14992 if(not checkDump(1, "2.20")
14993 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014994 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014995 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14996 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014997 return 0;
14998 }
14999 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015001 else
15002 {
15003 # typedef struct {...} type_t
15004 # typedef struct type_t {...} type_t
15005 if(index($TN1, " ".$TN2)!=-1)
15006 {
15007 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15008 return 0;
15009 }
15010 }
15011 if(index($TN2, " ".$TN1)!=-1)
15012 {
15013 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15014 return 0;
15015 }
15016 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015017
15018 if($TT1 eq "FuncPtr"
15019 and $TT2 eq "FuncPtr")
15020 {
15021 my $TN1_C = $TN1;
15022 my $TN2_C = $TN2;
15023
15024 $TN1_C=~s/\b(struct|union) //g;
15025 $TN2_C=~s/\b(struct|union) //g;
15026
15027 if($TN1_C eq $TN2_C) {
15028 return 0;
15029 }
15030 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015031 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015032
15033 my ($N1, $N2) = ($TN1, $TN2);
15034 $N1=~s/\b(struct|union) //g;
15035 $N2=~s/\b(struct|union) //g;
15036
15037 if($N1 eq $N2)
15038 { # QList<struct QUrl> and QList<QUrl>
15039 return 0;
15040 }
15041
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015042 return 1;
15043}
15044
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015045sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015046{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015047 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015048 if(defined $Cache{"differentDumps"}{$Check}) {
15049 return $Cache{"differentDumps"}{$Check};
15050 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015051 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015052 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015053 if($Check eq "G")
15054 {
15055 if(getGccVersion(1) ne getGccVersion(2))
15056 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015057 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015058 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015059 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015060 if($Check eq "V")
15061 {
15062 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15063 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15064 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015065 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015066 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015068 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015069 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015070}
15071
15072sub formatVersion($$)
15073{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015074 my ($V, $Digits) = @_;
15075 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015076 return join(".", splice(@Elems, 0, $Digits));
15077}
15078
15079sub htmlSpecChars($)
15080{
15081 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015082 if(not $Str) {
15083 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015085 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15086 $Str=~s/</&lt;/g;
15087 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15088 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015089 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15090 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015091 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015092 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015093 $Str=~s/\n/<br\/>/g;
15094 $Str=~s/\"/&quot;/g;
15095 $Str=~s/\'/&#39;/g;
15096 return $Str;
15097}
15098
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015099sub xmlSpecChars($)
15100{
15101 my $Str = $_[0];
15102 if(not $Str) {
15103 return $Str;
15104 }
15105
15106 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15107 $Str=~s/</&lt;/g;
15108 $Str=~s/>/&gt;/g;
15109
15110 $Str=~s/\"/&quot;/g;
15111 $Str=~s/\'/&#39;/g;
15112
15113 return $Str;
15114}
15115
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015116sub xmlSpecChars_R($)
15117{
15118 my $Str = $_[0];
15119 if(not $Str) {
15120 return $Str;
15121 }
15122
15123 $Str=~s/&amp;/&/g;
15124 $Str=~s/&lt;/</g;
15125 $Str=~s/&gt;/>/g;
15126
15127 $Str=~s/&quot;/"/g;
15128 $Str=~s/&#39;/'/g;
15129
15130 return $Str;
15131}
15132
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133sub black_name($)
15134{
15135 my $Name = $_[0];
15136 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15137}
15138
15139sub highLight_Signature($)
15140{
15141 my $Signature = $_[0];
15142 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15143}
15144
15145sub highLight_Signature_Italic_Color($)
15146{
15147 my $Signature = $_[0];
15148 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15149}
15150
15151sub separate_symbol($)
15152{
15153 my $Symbol = $_[0];
15154 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15155 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15156 ($Name, $Spec, $Ver) = ($1, $2, $3);
15157 }
15158 return ($Name, $Spec, $Ver);
15159}
15160
15161sub cut_f_attrs($)
15162{
15163 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15164 return $2;
15165 }
15166 return "";
15167}
15168
15169sub highLight_Signature_PPos_Italic($$$$$)
15170{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015171 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15172 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015173 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15174 my $Return = "";
15175 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15176 $Return = $2;
15177 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015178 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015179 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015180 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015181 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015182 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015183 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015184 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015185 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015186 }
15187 return $Signature;
15188 }
15189 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15190 $Begin.=" " if($Begin!~/ \Z/);
15191 $End = cut_f_attrs($Signature);
15192 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015193 my ($Short, $Params) = split_Signature($Signature);
15194 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015195 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015196 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015197 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015198 $Part=~s/\A\s+|\s+\Z//g;
15199 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15200 if($Part=~/\([\*]+(\w+)\)/i) {
15201 $ParamName = $1;#func-ptr
15202 }
15203 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15204 $ParamName = $1;
15205 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015206 if(not $ParamName)
15207 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015208 push(@Parts, $Part_Styled);
15209 next;
15210 }
15211 if($ItalicParams and not $TName_Tid{1}{$Part}
15212 and not $TName_Tid{2}{$Part})
15213 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015214 my $Style = "<i>$ParamName</i>";
15215
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015216 if($Param_Pos ne ""
15217 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015218 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015219 }
15220 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015221 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015222 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015223
15224 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015225 }
15226 $Part_Styled=~s/,(\w)/, $1/g;
15227 push(@Parts, $Part_Styled);
15228 }
15229 if(@Parts)
15230 {
15231 foreach my $Num (0 .. $#Parts)
15232 {
15233 if($Num==$#Parts)
15234 { # add ")" to the last parameter
15235 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15236 }
15237 elsif(length($Parts[$Num])<=45) {
15238 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15239 }
15240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015241 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015242 }
15243 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015244 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015245 }
15246 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015247 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015249 $Signature=~s!\[\]![&#160;]!g;
15250 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015251 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15252 if($SymbolVersion) {
15253 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15254 }
15255 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015256}
15257
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015258sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015259{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015260 my $Signature = $_[0];
15261 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15262 {
15263 $Signature=~s/\A\Q$ShortName\E\(//g;
15264 cut_f_attrs($Signature);
15265 $Signature=~s/\)\Z//;
15266 return ($ShortName, $Signature);
15267 }
15268
15269 # error
15270 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271}
15272
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015273sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015274{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015275 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015277 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15278 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015279 foreach my $Pos (0 .. length($Params) - 1)
15280 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015281 my $S = substr($Params, $Pos, 1);
15282 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015283 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015284 }
15285 if($S eq "," and
15286 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015287 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015288 if($Comma)
15289 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015290 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015291 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015292 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 }
15294 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015295 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015296 }
15297 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015298 if(not $Sp)
15299 { # remove spaces
15300 foreach (@Parts)
15301 {
15302 s/\A //g;
15303 s/ \Z//g;
15304 }
15305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015306 return @Parts;
15307}
15308
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015309sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310{
15311 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015312 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015313 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015314 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15315 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015316 $Center+=length($1);
15317 }
15318 foreach my $Pos (0 .. length($Sign)-1)
15319 {
15320 my $S = substr($Sign, $Pos, 1);
15321 if($S eq $Target)
15322 {
15323 if($B{"("}==$B{")"}
15324 and $B{"<"}==$B{">"}) {
15325 return $Center;
15326 }
15327 }
15328 if(defined $B{$S}) {
15329 $B{$S}+=1;
15330 }
15331 $Center+=1;
15332 }
15333 return 0;
15334}
15335
15336sub appendFile($$)
15337{
15338 my ($Path, $Content) = @_;
15339 return if(not $Path);
15340 if(my $Dir = get_dirname($Path)) {
15341 mkpath($Dir);
15342 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015343 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015344 print FILE $Content;
15345 close(FILE);
15346}
15347
15348sub writeFile($$)
15349{
15350 my ($Path, $Content) = @_;
15351 return if(not $Path);
15352 if(my $Dir = get_dirname($Path)) {
15353 mkpath($Dir);
15354 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015355 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015356 print FILE $Content;
15357 close(FILE);
15358}
15359
15360sub readFile($)
15361{
15362 my $Path = $_[0];
15363 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015364 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015365 local $/ = undef;
15366 my $Content = <FILE>;
15367 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015368 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015369 $Content=~s/\r/\n/g;
15370 }
15371 return $Content;
15372}
15373
15374sub get_filename($)
15375{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015376 if(defined $Cache{"get_filename"}{$_[0]}) {
15377 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015378 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015379 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15380 return ($Cache{"get_filename"}{$_[0]}=$1);
15381 }
15382 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015383}
15384
15385sub get_dirname($)
15386{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015387 if(defined $Cache{"get_dirname"}{$_[0]}) {
15388 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015389 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015390 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15391 return ($Cache{"get_dirname"}{$_[0]}=$1);
15392 }
15393 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015394}
15395
15396sub separate_path($) {
15397 return (get_dirname($_[0]), get_filename($_[0]));
15398}
15399
15400sub esc($)
15401{
15402 my $Str = $_[0];
15403 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15404 return $Str;
15405}
15406
15407sub readLineNum($$)
15408{
15409 my ($Path, $Num) = @_;
15410 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015411 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015412 foreach (1 ... $Num) {
15413 <FILE>;
15414 }
15415 my $Line = <FILE>;
15416 close(FILE);
15417 return $Line;
15418}
15419
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015420sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015422 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015423 return () if(not $Path or not -f $Path);
15424 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015425 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15426 {
15427 foreach my $AttrVal (split(/;/, $1))
15428 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015429 if($AttrVal=~/(.+):(.+)/)
15430 {
15431 my ($Name, $Value) = ($1, $2);
15432 $Attributes{$Name} = $Value;
15433 }
15434 }
15435 }
15436 return \%Attributes;
15437}
15438
15439sub is_abs($) {
15440 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15441}
15442
15443sub get_abs_path($)
15444{ # abs_path() should NOT be called for absolute inputs
15445 # because it can change them
15446 my $Path = $_[0];
15447 if(not is_abs($Path)) {
15448 $Path = abs_path($Path);
15449 }
15450 return $Path;
15451}
15452
15453sub get_OSgroup()
15454{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015455 my $N = $Config{"osname"};
15456 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015457 return "macos";
15458 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015459 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015460 return "bsd";
15461 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015462 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015463 return "beos";
15464 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015465 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015466 return "symbian";
15467 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015468 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015469 return "windows";
15470 }
15471 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015472 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015473 }
15474}
15475
15476sub getGccVersion($)
15477{
15478 my $LibVersion = $_[0];
15479 if($GCC_VERSION{$LibVersion})
15480 { # dump version
15481 return $GCC_VERSION{$LibVersion};
15482 }
15483 elsif($UsedDump{$LibVersion}{"V"})
15484 { # old-version dumps
15485 return "unknown";
15486 }
15487 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15488 if(not $GccVersion) {
15489 return "unknown";
15490 }
15491 return $GccVersion;
15492}
15493
15494sub showArch($)
15495{
15496 my $Arch = $_[0];
15497 if($Arch eq "arm"
15498 or $Arch eq "mips") {
15499 return uc($Arch);
15500 }
15501 return $Arch;
15502}
15503
15504sub getArch($)
15505{
15506 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015507
15508 if($TargetArch) {
15509 return $TargetArch;
15510 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015511 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015512 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015513 return $CPU_ARCH{$LibVersion};
15514 }
15515 elsif($UsedDump{$LibVersion}{"V"})
15516 { # old-version dumps
15517 return "unknown";
15518 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015519
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015520 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015521}
15522
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015523sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015524{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015525 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015526
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015527 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015528 if(getArch(1) ne getArch(2)
15529 or getArch(1) eq "unknown"
15530 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015531 { # don't show architecture in the header
15532 $ArchInfo="";
15533 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015534 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015535 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015536 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015537 }
15538 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015539 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015540 }
15541 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015542 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015543 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015544
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015545 my $V1 = $Descriptor{1}{"Version"};
15546 my $V2 = $Descriptor{2}{"Version"};
15547
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015548 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15549 {
15550 my $M1 = $UsedDump{1}{"M"};
15551 my $M2 = $UsedDump{2}{"M"};
15552
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015553 my $M1S = $M1;
15554 my $M2S = $M2;
15555
15556 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15557 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15558
15559 if($M1S eq $M2S
15560 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015561 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015562 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15563 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015564 }
15565 else
15566 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015567 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15568 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015569 }
15570 }
15571 else
15572 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015573 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015574 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015575 }
15576
15577 $Title .= $ArchInfo;
15578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015579 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015580 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015581 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015582 $Title = "<h1>".$Title."</h1>\n";
15583 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015584}
15585
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015586sub get_CheckedHeaders($)
15587{
15588 my $LibVersion = $_[0];
15589
15590 my @Headers = ();
15591
15592 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15593 {
15594 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015595
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015596 if(not is_target_header($File, $LibVersion)) {
15597 next;
15598 }
15599
15600 if(skipHeader($File, $LibVersion)) {
15601 next;
15602 }
15603
15604 push(@Headers, $Path);
15605 }
15606
15607 return @Headers;
15608}
15609
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610sub get_SourceInfo()
15611{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015612 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015613
15614 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015615 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015616 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15617 $CheckedHeaders .= "<div class='h_list'>\n";
15618 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 +040015619 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015620 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15621 my $Name = get_filename($Identity);
15622 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15623 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015624 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015625 $CheckedHeaders .= "</div>\n";
15626 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015628
15629 if(my @Sources = keys(%{$Registered_Sources{1}}))
15630 {
15631 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15632 $CheckedSources .= "<div class='h_list'>\n";
15633 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15634 {
15635 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15636 my $Name = get_filename($Identity);
15637 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15638 $CheckedSources .= $Name.$Comment."<br/>\n";
15639 }
15640 $CheckedSources .= "</div>\n";
15641 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15642 }
15643
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015644 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015645 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015646 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015647 $CheckedLibs .= "<div class='lib_list'>\n";
15648 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15649 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015650 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015651 $CheckedLibs .= $Library."<br/>\n";
15652 }
15653 $CheckedLibs .= "</div>\n";
15654 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015655 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015656
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015657 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15658}
15659
15660sub get_ObjTitle()
15661{
15662 if(defined $UsedDump{1}{"DWARF"}) {
15663 return "Objects";
15664 }
15665 else {
15666 return ucfirst($SLIB_TYPE)." Libraries";
15667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015668}
15669
15670sub get_TypeProblems_Count($$$)
15671{
15672 my ($TypeChanges, $TargetPriority, $Level) = @_;
15673 my $Type_Problems_Count = 0;
15674 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15675 {
15676 my %Kinds_Target = ();
15677 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15678 {
15679 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15680 {
15681 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015682 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15683 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 if($Kinds_Target{$Kind}{$Target}) {
15685 next;
15686 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015687
15688 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15689 {
15690 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15691 { # select a problem with the highest priority
15692 next;
15693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015694 }
15695 $Kinds_Target{$Kind}{$Target} = 1;
15696 $Type_Problems_Count += 1;
15697 }
15698 }
15699 }
15700 return $Type_Problems_Count;
15701}
15702
15703sub get_Summary($)
15704{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015705 my $Level = $_[0];
15706 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015707 $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 +040015708 %{$RESULT{$Level}} = (
15709 "Problems"=>0,
15710 "Warnings"=>0,
15711 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015712 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015713 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015715 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015716 {
15717 if(not defined $CompatRules{$Level}{$Kind})
15718 { # unknown rule
15719 if(not $UnknownRules{$Level}{$Kind})
15720 { # only one warning
15721 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15722 $UnknownRules{$Level}{$Kind}=1;
15723 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015724 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015725 }
15726 }
15727 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015728 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15729 {
15730 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15731 {
15732 if(not defined $CompatRules{$Level}{$Kind})
15733 { # unknown rule
15734 if(not $UnknownRules{$Level}{$Kind})
15735 { # only one warning
15736 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15737 $UnknownRules{$Level}{$Kind}=1;
15738 }
15739 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15740 }
15741 }
15742 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015743 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015745 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015746 {
15747 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15748 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015749 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015750 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015751 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015752 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015753 $Added += 1;
15754 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015755 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 {
15757 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015758 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015759 }
15760 else
15761 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015762 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015763 $I_Other += 1;
15764 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015765 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015766 $I_Problems_High += 1;
15767 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015768 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 $I_Problems_Medium += 1;
15770 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015771 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015772 $I_Problems_Low += 1;
15773 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015774 if(($Severity ne "Low" or $StrictCompat)
15775 and $Severity ne "Safe") {
15776 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015777 }
15778 }
15779 }
15780 }
15781 }
15782 }
15783 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015784 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015785 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015786 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015787 {
15788 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15789 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015790 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015791 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015792 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15793 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015794 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015795 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15796
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015797 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015798 { # select a problem with the highest priority
15799 next;
15800 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015801
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015802 if(($Severity ne "Low" or $StrictCompat)
15803 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015804 {
15805 if(defined $TotalAffected{$Level}{$Interface})
15806 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015807 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15808 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015809 }
15810 }
15811 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015812 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015814 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015815
15816 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15817
15818 if($MaxSeverity)
15819 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015820 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15821 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015822 }
15823 }
15824 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015825 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015827 }
15828 }
15829 }
15830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015832 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15833 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15834 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15835 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015836
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015837 %TypeChanges = (); # free memory
15838
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015839 # changed and removed public symbols
15840 my $SCount = keys(%{$CheckedSymbols{$Level}});
15841 if($ExtendedCheck)
15842 { # don't count external_func_0 for constants
15843 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015844 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015845 if($SCount)
15846 {
15847 my %Weight = (
15848 "High" => 100,
15849 "Medium" => 50,
15850 "Low" => 25
15851 );
15852 foreach (keys(%{$TotalAffected{$Level}})) {
15853 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015854 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015855 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015856 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015857 else {
15858 $RESULT{$Level}{"Affected"} = 0;
15859 }
15860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15862 if($RESULT{$Level}{"Affected"}>=100) {
15863 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015864 }
15865
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015866 $RESULT{$Level}{"Problems"} += $Removed;
15867 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015868 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015869 if($StrictCompat) {
15870 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15871 }
15872 else {
15873 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015875
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015876 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015877 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015878 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015879 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015880 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015881 if($Severity eq "Safe")
15882 {
15883 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015884 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015885 elsif($Severity eq "Low")
15886 {
15887 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015889 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015890 }
15891
15892 if($C_Problems_Low)
15893 {
15894 if($StrictCompat) {
15895 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15896 }
15897 else {
15898 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015899 }
15900 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015901 if($RESULT{$Level}{"Problems"}
15902 and $RESULT{$Level}{"Affected"}) {
15903 $RESULT{$Level}{"Verdict"} = "incompatible";
15904 }
15905 else {
15906 $RESULT{$Level}{"Verdict"} = "compatible";
15907 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015908
15909 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15910 if(not $TotalTypes)
15911 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015912 $TotalTypes = keys(%{$TName_Tid{1}});
15913 }
15914
15915 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15916 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15917
15918 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15919
15920 if($ReportFormat eq "xml")
15921 { # XML
15922 # test info
15923 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15924 $TestInfo .= " <version1>\n";
15925 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015926 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015927 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15928 $TestInfo .= " </version1>\n";
15929
15930 $TestInfo .= " <version2>\n";
15931 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015932 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15934 $TestInfo .= " </version2>\n";
15935 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15936
15937 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015938 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015939 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015940 $TestResults .= " <headers>\n";
15941 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15942 {
15943 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15944 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15945 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15946 }
15947 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015949
15950 if(my @Sources = keys(%{$Registered_Sources{1}}))
15951 {
15952 $TestResults .= " <sources>\n";
15953 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15954 {
15955 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15956 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15957 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15958 }
15959 $TestResults .= " </sources>\n";
15960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961
15962 $TestResults .= " <libs>\n";
15963 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15964 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015965 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015966 $TestResults .= " <name>$Library</name>\n";
15967 }
15968 $TestResults .= " </libs>\n";
15969
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015970 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015971 $TestResults .= " <types>".$TotalTypes."</types>\n";
15972
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015973 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15974 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015975 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15976
15977 # problem summary
15978 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15979 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15980
15981 $Problem_Summary .= " <problems_with_types>\n";
15982 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15983 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15984 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15985 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15986 $Problem_Summary .= " </problems_with_types>\n";
15987
15988 $Problem_Summary .= " <problems_with_symbols>\n";
15989 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15990 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15991 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015992 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993 $Problem_Summary .= " </problems_with_symbols>\n";
15994
15995 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015996 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015997 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015998
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015999 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16000
16001 return ($TestInfo.$TestResults.$Problem_Summary, "");
16002 }
16003 else
16004 { # HTML
16005 # test info
16006 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016007 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016008
16009 if($TargetComponent eq "library") {
16010 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16011 }
16012 else {
16013 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015
16016 my (@VInf1, @VInf2, $AddTestInfo) = ();
16017 if($Arch1 ne "unknown"
16018 and $Arch2 ne "unknown")
16019 { # CPU arch
16020 if($Arch1 eq $Arch2)
16021 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016022 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016023 }
16024 else
16025 { # go to the version number
16026 push(@VInf1, showArch($Arch1));
16027 push(@VInf2, showArch($Arch2));
16028 }
16029 }
16030 if($GccV1 ne "unknown"
16031 and $GccV2 ne "unknown"
16032 and $OStarget ne "windows")
16033 { # GCC version
16034 if($GccV1 eq $GccV2)
16035 { # go to the separate section
16036 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16037 }
16038 else
16039 { # go to the version number
16040 push(@VInf1, "gcc ".$GccV1);
16041 push(@VInf2, "gcc ".$GccV2);
16042 }
16043 }
16044 # show long version names with GCC version and CPU architecture name (if different)
16045 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16046 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16047 $TestInfo .= $AddTestInfo;
16048 #if($COMMON_LANGUAGE{1}) {
16049 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16050 #}
16051 if($ExtendedCheck) {
16052 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16053 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016054 if($JoinReport)
16055 {
16056 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016057 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016058 }
16059 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016060 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016061 }
16062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 $TestInfo .= "</table>\n";
16064
16065 # test results
16066 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016067 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016068
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016069 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016070 {
16071 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16072 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16073 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016074
16075 if(my @Sources = keys(%{$Registered_Sources{1}}))
16076 {
16077 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16078 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016080
16081 if(not $ExtendedCheck)
16082 {
16083 my $Libs_Link = "0";
16084 $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 +040016085 $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 +040016086 }
16087
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016088 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016089
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016090 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016091 if($JoinReport) {
16092 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16093 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016094 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016095 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016096 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16097 }
16098 else {
16099 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16100 }
16101 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016102 $TestResults .= "</table>\n";
16103
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016104 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016105 # problem summary
16106 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016107 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016108 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16109
16110 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016111 if($Added>0)
16112 {
16113 if($JoinReport) {
16114 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16115 }
16116 else {
16117 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16118 }
16119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016120 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016121 $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 +040016122
16123 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016124 if($Removed>0)
16125 {
16126 if($JoinReport) {
16127 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16128 }
16129 else {
16130 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16131 }
16132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016133 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016134 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16135 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016136
16137 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016138 $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 +040016139 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016140 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16141 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016142
16143 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016144 $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 +040016145 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016146 $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 +040016147
16148 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016149 $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 +040016150 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016151 $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 +040016152
16153 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016154 $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 +040016155 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016156 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16157 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016158
16159 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016160 $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 +040016161 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016162 $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 +040016163
16164 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016165 $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 +040016166 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016167 $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 +040016168
16169 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016170 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16171 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016172 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016173 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016174 $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 +040016175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016176 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016177 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016178 {
16179 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016180 $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 +030016181 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016183
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016184 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016185 {
16186 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016187 $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 +030016188 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016190
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016191 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016192 {
16193 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16194 $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 +030016195 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016196 }
16197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016198 $META_DATA .= "tool_version:$TOOL_VERSION";
16199 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016200 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016201 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16202 }
16203}
16204
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016205sub getStyle($$$)
16206{
16207 my ($Subj, $Act, $Num) = @_;
16208 my %Style = (
16209 "A"=>"new",
16210 "R"=>"failed",
16211 "S"=>"passed",
16212 "L"=>"warning",
16213 "M"=>"failed",
16214 "H"=>"failed"
16215 );
16216 if($Num>0) {
16217 return " class='".$Style{$Act}."'";
16218 }
16219 return "";
16220}
16221
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222sub show_number($)
16223{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016224 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016225 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016226 my $Num = cut_off_number($_[0], 2, 0);
16227 if($Num eq "0")
16228 {
16229 foreach my $P (3 .. 7)
16230 {
16231 $Num = cut_off_number($_[0], $P, 1);
16232 if($Num ne "0") {
16233 last;
16234 }
16235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016236 }
16237 if($Num eq "0") {
16238 $Num = $_[0];
16239 }
16240 return $Num;
16241 }
16242 return $_[0];
16243}
16244
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016246{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 if($num!~/\./)
16249 {
16250 $num .= ".";
16251 foreach (1 .. $digs_to_cut-1) {
16252 $num .= "0";
16253 }
16254 }
16255 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16256 {
16257 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16258 $num .= "0";
16259 }
16260 }
16261 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16262 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16263 }
16264 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016265 if($z) {
16266 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 return $num;
16269}
16270
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016271sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016273 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016274 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016275
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016276 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016277 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16278 {
16279 my $Header = $Constants{1}{$Constant}{"Header"};
16280 if(not $Header)
16281 { # added
16282 $Header = $Constants{2}{$Constant}{"Header"}
16283 }
16284
16285 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16286 {
16287 if(not defined $CompatRules{$Level}{$Kind}) {
16288 next;
16289 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016290 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016291 next;
16292 }
16293 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016295 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016296
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016297 if($ReportFormat eq "xml")
16298 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016299 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 {
16301 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016302 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303 {
16304 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016305 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16306 {
16307 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16308 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16309 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016310
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016311 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16312 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16313 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016314 if($Overcome) {
16315 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16316 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016317 $CHANGED_CONSTANTS .= " </problem>\n";
16318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016319 $CHANGED_CONSTANTS .= " </constant>\n";
16320 }
16321 $CHANGED_CONSTANTS .= " </header>\n";
16322 }
16323 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16324 }
16325 else
16326 { # HTML
16327 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016328 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 {
16330 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016331 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016332 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016333 my $Report = "";
16334
16335 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16336 {
16337 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16338 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016339 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016340 $Number += 1;
16341 }
16342 if($Report)
16343 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016344 $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 +030016345 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016346 $Report = insertIDs($Report);
16347 }
16348 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016349 }
16350 $CHANGED_CONSTANTS .= "<br/>\n";
16351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016352 if($CHANGED_CONSTANTS)
16353 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016354 my $Title = "Problems with Constants, $TargetSeverity Severity";
16355 if($TargetSeverity eq "Safe")
16356 { # Safe Changes
16357 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016358 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016359 $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 +040016360 }
16361 }
16362 return $CHANGED_CONSTANTS;
16363}
16364
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016365sub getTitle($$$)
16366{
16367 my ($Header, $Library, $NameSpace) = @_;
16368 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016369
16370 # if($Library and $Library!~/\.\w+\Z/) {
16371 # $Library .= " (.$LIB_EXT)";
16372 # }
16373
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016374 if($Header and $Library)
16375 {
16376 $Title .= "<span class='h_name'>$Header</span>";
16377 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16378 }
16379 elsif($Library) {
16380 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16381 }
16382 elsif($Header) {
16383 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16384 }
16385 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016386 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016387 }
16388 return $Title;
16389}
16390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016391sub get_Report_Added($)
16392{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016394 my $ADDED_INTERFACES = "";
16395 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016396 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016398 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016399 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016400 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016401 {
16402 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16403 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016404 if($Level eq "Source" and $ReportFormat eq "html")
16405 { # do not show library name in HTML report
16406 $DyLib = "";
16407 }
16408 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016409 }
16410 }
16411 }
16412 if($ReportFormat eq "xml")
16413 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 {
16416 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016417 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016418 {
16419 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16422 }
16423 $ADDED_INTERFACES .= " </library>\n";
16424 }
16425 $ADDED_INTERFACES .= " </header>\n";
16426 }
16427 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16428 }
16429 else
16430 { # HTML
16431 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016432 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016433 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016434 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016436 my %NameSpaceSymbols = ();
16437 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016438 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016439 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016442 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16443 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 foreach my $Interface (@SortedInterfaces)
16445 {
16446 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 my $Signature = get_Signature($Interface, 2);
16448 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016449 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016450 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016451 if($Interface=~/\A(_Z|\?)/)
16452 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016454 $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 +040016455 }
16456 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016457 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016458 }
16459 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016460 else
16461 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016462 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016463 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016464 }
16465 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016466 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016467 }
16468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016470 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 }
16473 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016474 if($ADDED_INTERFACES)
16475 {
16476 my $Anchor = "<a name='Added'></a>";
16477 if($JoinReport) {
16478 $Anchor = "<a name='".$Level."_Added'></a>";
16479 }
16480 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 }
16482 }
16483 return $ADDED_INTERFACES;
16484}
16485
16486sub get_Report_Removed($)
16487{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016488 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016489 my $REMOVED_INTERFACES = "";
16490 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016491 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016492 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016493 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016495 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016496 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016497 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16498 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016499 if($Level eq "Source" and $ReportFormat eq "html")
16500 { # do not show library name in HTML report
16501 $DyLib = "";
16502 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016503 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 }
16505 }
16506 }
16507 if($ReportFormat eq "xml")
16508 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016509 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016510 {
16511 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016512 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 {
16514 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016515 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16516 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016517 }
16518 $REMOVED_INTERFACES .= " </library>\n";
16519 }
16520 $REMOVED_INTERFACES .= " </header>\n";
16521 }
16522 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16523 }
16524 else
16525 { # HTML
16526 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016527 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016528 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016529 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016530 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016531 my %NameSpaceSymbols = ();
16532 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016533 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016534 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016535 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016536 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016537 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16538 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016539 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 {
16541 $Removed_Number += 1;
16542 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016543 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016545 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016547 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016549 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016550 $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 +040016551 }
16552 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016553 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 }
16555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 else
16557 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016558 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
16561 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016562 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 }
16564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016565 }
16566 }
16567 $REMOVED_INTERFACES .= "<br/>\n";
16568 }
16569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 if($REMOVED_INTERFACES)
16571 {
16572 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16573 if($JoinReport) {
16574 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16575 }
16576 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 }
16578 }
16579 return $REMOVED_INTERFACES;
16580}
16581
16582sub getXmlParams($$)
16583{
16584 my ($Content, $Problem) = @_;
16585 return "" if(not $Content or not $Problem);
16586 my %XMLparams = ();
16587 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16588 {
16589 my $Macro = "\@".lc($Attr);
16590 if($Content=~/\Q$Macro\E/) {
16591 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16592 }
16593 }
16594 my @PString = ();
16595 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016596 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016597 }
16598 if(@PString) {
16599 return " ".join(" ", @PString);
16600 }
16601 else {
16602 return "";
16603 }
16604}
16605
16606sub addMarkup($)
16607{
16608 my $Content = $_[0];
16609 # auto-markup
16610 $Content=~s/\n[ ]*//; # spaces
16611 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16612 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016613 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016614 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16615 if($Content=~/\ANOTE:/)
16616 { # notes
16617 $Content=~s!(NOTE):!<b>$1</b>:!g;
16618 }
16619 else {
16620 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16621 }
16622 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16623 my @Keywords = (
16624 "void",
16625 "const",
16626 "static",
16627 "restrict",
16628 "volatile",
16629 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016630 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016631 );
16632 my $MKeys = join("|", @Keywords);
16633 foreach (@Keywords) {
16634 $MKeys .= "|non-".$_;
16635 }
16636 $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 +040016637
16638 # Markdown
16639 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16640 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 return $Content;
16642}
16643
16644sub applyMacroses($$$$)
16645{
16646 my ($Level, $Kind, $Content, $Problem) = @_;
16647 return "" if(not $Content or not $Problem);
16648 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16649 $Content = addMarkup($Content);
16650 # macros
16651 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16652 {
16653 my $Macro = "\@".lc($Attr);
16654 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016655 if(not defined $Value
16656 or $Value eq "") {
16657 next;
16658 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016659
16660 if(index($Content, $Macro)==-1) {
16661 next;
16662 }
16663
16664 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16665 and $Kind!~/_Type_/
16666 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016668 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016669 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016670 $Value = black_name($Value);
16671 }
16672 elsif($Value=~/\s/) {
16673 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16674 }
16675 elsif($Value=~/\A\d+\Z/
16676 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16677 { # bits to bytes
16678 if($Value % $BYTE_SIZE)
16679 { # bits
16680 if($Value==1) {
16681 $Value = "<b>".$Value."</b> bit";
16682 }
16683 else {
16684 $Value = "<b>".$Value."</b> bits";
16685 }
16686 }
16687 else
16688 { # bytes
16689 $Value /= $BYTE_SIZE;
16690 if($Value==1) {
16691 $Value = "<b>".$Value."</b> byte";
16692 }
16693 else {
16694 $Value = "<b>".$Value."</b> bytes";
16695 }
16696 }
16697 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016698 else
16699 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016700 $Value = "<b>".htmlSpecChars($Value)."</b>";
16701 }
16702 $Content=~s/\Q$Macro\E/$Value/g;
16703 }
16704
16705 if($Content=~/(\A|[^\@\w])\@\w/)
16706 {
16707 if(not $IncompleteRules{$Level}{$Kind})
16708 { # only one warning
16709 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16710 $IncompleteRules{$Level}{$Kind} = 1;
16711 }
16712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 return $Content;
16714}
16715
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016716sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016717{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016719 my $INTERFACE_PROBLEMS = "";
16720 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016721
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016724 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16725 if($SV and defined $CompatProblems{$Level}{$SN}) {
16726 next;
16727 }
16728 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 {
16730 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016731 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016732 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016733 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16734 my $DyLib = $Symbol_Library{1}{$Symbol};
16735 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016736 { # Symbol with Version
16737 $DyLib = $Symbol_Library{1}{$VSym};
16738 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016739 if(not $DyLib)
16740 { # const global data
16741 $DyLib = "";
16742 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016743 if($Level eq "Source" and $ReportFormat eq "html")
16744 { # do not show library name in HTML report
16745 $DyLib = "";
16746 }
16747 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16748 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016749 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016750 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16751 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 }
16754 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016755 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16756 {
16757 delete($SymbolChanges{$Symbol}{$Kind});
16758 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016760 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016761 }
16762 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016763 if(not keys(%{$SymbolChanges{$Symbol}})) {
16764 delete($SymbolChanges{$Symbol});
16765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016766 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 if($ReportFormat eq "xml")
16769 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016770 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016771 {
16772 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016773 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016774 {
16775 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016776 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16777 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016778 {
16779 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016780 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016781 {
16782 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16783 {
16784 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016785 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016787 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16788 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16789 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16790 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16791 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016792 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16793 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016795 $INTERFACE_PROBLEMS .= " </problem>\n";
16796 }
16797 }
16798 $INTERFACE_PROBLEMS .= " </symbol>\n";
16799 }
16800 $INTERFACE_PROBLEMS .= " </library>\n";
16801 }
16802 $INTERFACE_PROBLEMS .= " </header>\n";
16803 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016804 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016805 }
16806 else
16807 { # HTML
16808 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016809 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016810 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016811 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016812 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 my (%NameSpaceSymbols, %NewSignature) = ();
16814 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016815 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016816 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016817 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016818 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016819 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016820 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 +040016821 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016822 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016823 my $Signature = get_Signature($Symbol, 1);
16824 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016825 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016826 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016827 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016828 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016829 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016830 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016831 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016832 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016834 }
16835 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16836 {
16837 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016838 $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 +040016839 $ProblemNum += 1;
16840 $ProblemsNum += 1;
16841 }
16842 }
16843 }
16844 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016845 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016846 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016847 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016848 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016849 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016850 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016851
16852 if($NameSpace)
16853 {
16854 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16855 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016857
16858 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol." ($ProblemNum)".$ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016859 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016860
16861 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016862 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016863 if($NameSpace) {
16864 $NSign = cut_Namespace($NSign, $NameSpace);
16865 }
16866 $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 +040016867 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016868
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 if($Symbol=~/\A(_Z|\?)/) {
16870 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16871 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016872
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016873 $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 +040016874 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 }
16876 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016877 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878 }
16879 }
16880 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016881
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 if($INTERFACE_PROBLEMS)
16883 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016884 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16885 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16886 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887 { # Safe Changes
16888 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016890 $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 +040016891 }
16892 }
16893 return $INTERFACE_PROBLEMS;
16894}
16895
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016896sub cut_Namespace($$)
16897{
16898 my ($N, $Ns) = @_;
16899 $N=~s/\b\Q$Ns\E:://g;
16900 return $N;
16901}
16902
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903sub get_Report_TypeProblems($$)
16904{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016905 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016906 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016907 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016908
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016909 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016911 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 {
16913 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16914 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016915 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016916 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016917 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016918 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016919 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016920
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016921 if($Severity eq "Safe"
16922 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016923 next;
16924 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016925
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016926 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16927 {
16928 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16929 { # select a problem with the highest priority
16930 next;
16931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016933
16934 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 }
16936 }
16937 }
16938 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016939
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 my %Kinds_Locations = ();
16941 foreach my $TypeName (keys(%TypeChanges))
16942 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016943 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16945 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016946 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016948 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016949 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 { # other priority
16951 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16952 next;
16953 }
16954 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16955 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016956 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016957 { # duplicate target
16958 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16959 next;
16960 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016961 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016962 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016963 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 }
16965 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16966 delete($TypeChanges{$TypeName}{$Kind});
16967 }
16968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 if(not keys(%{$TypeChanges{$TypeName}})) {
16970 delete($TypeChanges{$TypeName});
16971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016973
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016974 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 +040016975 if($ReportFormat eq "xml")
16976 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016977 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 {
16979 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016982 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016983 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16984 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016985 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016986 {
16987 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16988 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16989 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16990 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16991 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16992 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016993 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16994 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016996 $TYPE_PROBLEMS .= " </problem>\n";
16997 }
16998 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016999 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017000 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017001 $TYPE_PROBLEMS .= showVTables($TypeName);
17002 }
17003 $TYPE_PROBLEMS .= " </type>\n";
17004 }
17005 $TYPE_PROBLEMS .= " </header>\n";
17006 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017007 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017008 }
17009 else
17010 { # HTML
17011 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017012 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017013 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017014 my (%NameSpace_Type) = ();
17015 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017016 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017017 }
17018 foreach my $NameSpace (sort keys(%NameSpace_Type))
17019 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017020 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017021 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 +040017022 foreach my $TypeName (@SortedTypes)
17023 {
17024 my $ProblemNum = 1;
17025 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017026
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017027 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17028 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017029 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017030 {
17031 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17032 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17033 {
17034 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017035 $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 +040017036 $ProblemNum += 1;
17037 $ProblemsNum += 1;
17038 }
17039 }
17040 }
17041 $ProblemNum -= 1;
17042 if($TYPE_REPORT)
17043 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017044 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017046 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 $ShowVTables = showVTables($TypeName);
17048 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017049
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017050 my $ShowType = show_Type($TypeName, 1, 1);
17051
17052 if($NameSpace)
17053 {
17054 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17055 $ShowType = cut_Namespace($ShowType, $NameSpace);
17056 $Affected = cut_Namespace($Affected, $NameSpace);
17057 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17058 }
17059
17060 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017061 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17062 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17063 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17064 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 }
17066 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017067 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017068 }
17069 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017071 if($TYPE_PROBLEMS)
17072 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017073 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17074 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017075 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017076 { # Safe Changes
17077 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017079 $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 +040017080 }
17081 }
17082 return $TYPE_PROBLEMS;
17083}
17084
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017085sub show_Type($$$)
17086{
17087 my ($Name, $Html, $LibVersion) = @_;
17088 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17089 $TType = lc($TType);
17090 if($TType=~/struct|union|enum/) {
17091 $Name=~s/\A\Q$TType\E //g;
17092 }
17093 if($Html) {
17094 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17095 }
17096 else {
17097 $Name = $TType." ".$Name;
17098 }
17099 return $Name;
17100}
17101
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017102sub get_Anchor($$$)
17103{
17104 my ($Kind, $Level, $Severity) = @_;
17105 if($JoinReport)
17106 {
17107 if($Severity eq "Safe") {
17108 return "Other_".$Level."_Changes_In_".$Kind."s";
17109 }
17110 else {
17111 return $Kind."_".$Level."_Problems_".$Severity;
17112 }
17113 }
17114 else
17115 {
17116 if($Severity eq "Safe") {
17117 return "Other_Changes_In_".$Kind."s";
17118 }
17119 else {
17120 return $Kind."_Problems_".$Severity;
17121 }
17122 }
17123}
17124
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125sub showVTables($)
17126{
17127 my $TypeName = $_[0];
17128 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017129 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017130 if(defined $Type1{"VTable"}
17131 and keys(%{$Type1{"VTable"}}))
17132 {
17133 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017134 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 if(defined $Type2{"VTable"}
17136 and keys(%{$Type2{"VTable"}}))
17137 {
17138 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17139 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017140 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017141 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017142 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17143 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017144 }
17145 my $VTABLES = "";
17146 if($ReportFormat eq "xml")
17147 { # XML
17148 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017149 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017150 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017151 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017152 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17153 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017154 $VTABLES .= " </entry>\n";
17155 }
17156 $VTABLES .= " </vtable>\n\n";
17157 }
17158 else
17159 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017160 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017161 $VTABLES .= "<tr><th>Offset</th>";
17162 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017163 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017164 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017165 {
17166 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017167
17168 my $E1 = $Entries{$Index}{"E1"};
17169 my $E2 = $Entries{$Index}{"E2"};
17170
17171 if($E1 ne $E2
17172 and $E1!~/ 0x/
17173 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017174 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017175 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017177 $Color1 = " class='failed'";
17178 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 }
17180 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017181 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017182 }
17183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017184 $VTABLES .= "<tr><th>".$Index."</th>\n";
17185 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17186 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 }
17188 $VTABLES .= "</table><br/>\n";
17189 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017190 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017191 }
17192 return $VTABLES;
17193 }
17194 }
17195 return "";
17196}
17197
17198sub simpleVEntry($)
17199{
17200 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017201 if(not defined $VEntry
17202 or $VEntry eq "") {
17203 return "";
17204 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017205
17206 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017207 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17208 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17209 if($VEntry=~/\A_ZThn.+\Z/) {
17210 $VEntry = "non-virtual thunk";
17211 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017212 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017213 # support for old GCC versions
17214 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17215 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17216 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017217 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17218 return $VEntry;
17219}
17220
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017221sub adjustParamPos($$$)
17222{
17223 my ($Pos, $Symbol, $LibVersion) = @_;
17224 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17225 {
17226 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17227 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17228 {
17229 return $Pos-1;
17230 }
17231
17232 return $Pos;
17233 }
17234
17235 return undef;
17236}
17237
17238sub getParamPos($$$)
17239{
17240 my ($Name, $Symbol, $LibVersion) = @_;
17241
17242 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17243 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17244 {
17245 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17246 foreach (keys(%{$Info->{"Param"}}))
17247 {
17248 if($Info->{"Param"}{$_}{"name"} eq $Name)
17249 {
17250 return $_;
17251 }
17252 }
17253 }
17254
17255 return undef;
17256}
17257
17258sub getParamName($)
17259{
17260 my $Loc = $_[0];
17261 $Loc=~s/\->.*//g;
17262 return $Loc;
17263}
17264
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017265sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017266{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017267 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017268
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017269 my $LIMIT = 10;
17270 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017271 $LIMIT = $AffectLimit;
17272 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017273
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017274 my @Kinds = sort keys(%{$Kinds_Locations});
17275 my %KLocs = ();
17276 foreach my $Kind (@Kinds)
17277 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017278 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 +030017279 $KLocs{$Kind} = \@Locs;
17280 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017281
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017282 my %SymLocKind = ();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017283 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017284 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017285 if(index($Symbol, "_Z")==0
17286 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017287 { # duplicated problems for C2 constructors, D2 and D0 destructors
17288 next;
17289 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017290
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017291 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017292 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017293 if(not defined $CompatProblems{$Level}{$Symbol}
17294 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17295 next;
17296 }
17297
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017298 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017299 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017300 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017301 next;
17302 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017303
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017304 if(index($Symbol, "\@")!=-1
17305 or index($Symbol, "\$")!=-1)
17306 {
17307 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17308
17309 if($Level eq "Source")
17310 { # remove symbol version
17311 $Symbol = $SN;
17312 }
17313
17314 if($SV and defined $CompatProblems{$Level}{$SN}
17315 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17316 { # duplicated problems for versioned symbols
17317 next;
17318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017319 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017320
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017321 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017322 if($Type_Name ne $Target_TypeName) {
17323 next;
17324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017325
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017326 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017327 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017328 }
17329 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017330
17331 # if(keys(%SymLocKind)>=$LIMIT)
17332 # {
17333 # last;
17334 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017335 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017336
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017337 %KLocs = (); # clear
17338
17339 my %SymSel = ();
17340 my $Num = 0;
17341 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017342 {
17343 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17344 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017345 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017346 {
17347 $SymSel{$Symbol}{"Loc"} = $Loc;
17348 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017349 last LOOP;
17350 }
17351 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017352
17353 $Num += 1;
17354
17355 if($Num>=$LIMIT) {
17356 last;
17357 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017358 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017359
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017360 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362 if($ReportFormat eq "xml")
17363 { # XML
17364 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017365
17366 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017367 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017368 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017369 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017370 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017373 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017374 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017375 $Target .= " param=\"$PName\"";
17376 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017377 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017378 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017379 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017381 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017382 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017383 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017384
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017385 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017386 $Target .= " field=\"$1\"";
17387 }
17388
17389 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017390 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391 $Affected .= " </symbol>\n";
17392 }
17393 $Affected .= " </affected>\n";
17394 }
17395 else
17396 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017397 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017398 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017399 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17400 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017401 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017402 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17403
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017404 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017405 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017406 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017407
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017408 if(keys(%SymLocKind)>$LIMIT) {
17409 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017410 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017411
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017412 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017413 if($Affected)
17414 {
17415 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017416 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymLocKind).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017417 }
17418 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017420 return $Affected;
17421}
17422
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017423sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017424{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017425 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017426 if($L2=~/\A(retval|this)\b/
17427 and $L1!~/\A(retval|this)\b/)
17428 {
17429 if($L1!~/\-\>/) {
17430 return 1;
17431 }
17432 elsif($L2=~/\-\>/) {
17433 return 1;
17434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017435 }
17436 return 0;
17437}
17438
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017439sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017440{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017441 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017442
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017443 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017444
17445 my $Location_I = $Location;
17446 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17447
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017450 if($Kind eq "Overridden_Virtual_Method"
17451 or $Kind eq "Overridden_Virtual_Method_B") {
17452 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17453 }
17454 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17455 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017456 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17457
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017458 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17459 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017460 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17461 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17462
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017463 if($ClassName eq $Problem{"Type_Name"}) {
17464 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17465 }
17466 else {
17467 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17468 }
17469 }
17470 else
17471 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017472 my $TypeID = undef;
17473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474 if($Location=~/retval/)
17475 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017476 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017477 push(@Sentence, "Field \'".$Location."\' in return value");
17478 }
17479 else {
17480 push(@Sentence, "Return value");
17481 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017482
17483 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017484 }
17485 elsif($Location=~/this/)
17486 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017487 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017488 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17489 }
17490 else {
17491 push(@Sentence, "\'this\' pointer");
17492 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017493
17494 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017495 }
17496 else
17497 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017498
17499 my $PName = getParamName($Location);
17500 my $PPos = getParamPos($PName, $Symbol, 1);
17501
17502 if(index($Location, "->")!=-1) {
17503 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 }
17505 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017506 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017507 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017508 if($PName) {
17509 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017510 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017511
17512 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17513 }
17514
17515 if($Location!~/this/)
17516 {
17517 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017518 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017519 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017520 push(@Sentence, "(pointer)");
17521 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017522 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017523 push(@Sentence, "(reference)");
17524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017525 }
17526 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017528 if($Location eq "this") {
17529 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17530 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017531 else
17532 {
17533 my $Location_T = $Location;
17534 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17535
17536 my $TypeID_Problem = $TypeID;
17537 if($Location_T) {
17538 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17539 }
17540
17541 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17542 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17543 }
17544 else {
17545 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017547 }
17548 }
17549 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017550 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017551 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 +040017552 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017553
17554 my $Sent = join(" ", @Sentence);
17555
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017556 $Sent=~s/->/./g;
17557
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017558 if($ReportFormat eq "xml")
17559 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017560 $Sent=~s/'//g;
17561 }
17562
17563 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017564}
17565
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017566sub getFieldType($$$)
17567{
17568 my ($Location, $TypeId, $LibVersion) = @_;
17569
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017570 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017571
17572 foreach my $Name (@Fields)
17573 {
17574 my %Info = get_BaseType($TypeId, $LibVersion);
17575
17576 foreach my $Pos (keys(%{$Info{"Memb"}}))
17577 {
17578 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17579 {
17580 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17581 last;
17582 }
17583 }
17584 }
17585
17586 return $TypeId;
17587}
17588
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017589sub get_XmlSign($$)
17590{
17591 my ($Symbol, $LibVersion) = @_;
17592 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17593 my $Report = "";
17594 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17595 {
17596 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017597 my $Type = $Info->{"Param"}{$Pos}{"type"};
17598 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017599 foreach my $Typedef (keys(%ChangedTypedef))
17600 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017601 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17602 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017604 }
17605 $Report .= " <param pos=\"$Pos\">\n";
17606 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017607 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017608 $Report .= " </param>\n";
17609 }
17610 if(my $Return = $Info->{"Return"})
17611 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017612 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017613 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017614 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017615 $Report .= " </retval>\n";
17616 }
17617 return $Report;
17618}
17619
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017620sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017621{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017622 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017623 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017624 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017625 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017626 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17627 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017628 next;
17629 }
17630 $Report .= " <symbol name=\"$Symbol\">\n";
17631 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017632 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017633 {
17634 if(defined $CompleteSignature{1}{$Symbol}
17635 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17636 {
17637 $P1 = get_XmlSign($Symbol, 1);
17638 $S1 = get_Signature($Symbol, 1);
17639 }
17640 elsif($Symbol=~/\A(_Z|\?)/) {
17641 $S1 = $tr_name{$Symbol};
17642 }
17643 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017644 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017645 {
17646 if(defined $CompleteSignature{2}{$Symbol}
17647 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17648 {
17649 $P2 = get_XmlSign($Symbol, 2);
17650 $S2 = get_Signature($Symbol, 2);
17651 }
17652 elsif($Symbol=~/\A(_Z|\?)/) {
17653 $S2 = $tr_name{$Symbol};
17654 }
17655 }
17656 if($S1)
17657 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017658 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017659 $Report .= $P1;
17660 $Report .= " </old>\n";
17661 }
17662 if($S2 and $S2 ne $S1)
17663 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017664 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017665 $Report .= $P2;
17666 $Report .= " </new>\n";
17667 }
17668 $Report .= " </symbol>\n";
17669 }
17670 $Report .= "</symbols_info>\n";
17671 return $Report;
17672}
17673
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017674sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017675{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017676 my ($Level, $Report) = @_;
17677 if($ReportFormat eq "xml") {
17678 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017679 }
17680 if($StdOut)
17681 { # --stdout option
17682 print STDOUT $Report;
17683 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017684 else
17685 {
17686 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017687 mkpath(get_dirname($RPath));
17688
17689 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17690 print REPORT $Report;
17691 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017692 }
17693}
17694
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017695sub getReport($)
17696{
17697 my $Level = $_[0];
17698 if($ReportFormat eq "xml")
17699 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017700 if($Level eq "Join")
17701 {
17702 my $Report = "<reports>\n";
17703 $Report .= getReport("Binary");
17704 $Report .= getReport("Source");
17705 $Report .= "</reports>\n";
17706 return $Report;
17707 }
17708 else
17709 {
17710 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17711 my ($Summary, $MetaData) = get_Summary($Level);
17712 $Report .= $Summary."\n";
17713 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17714 $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 +040017715
17716 # additional symbols info (if needed)
17717 # $Report .= get_Report_SymbolsInfo($Level);
17718
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017719 $Report .= "</report>\n";
17720 return $Report;
17721 }
17722 }
17723 else
17724 { # HTML
17725 my $CssStyles = readModule("Styles", "Report.css");
17726 my $JScripts = readModule("Scripts", "Sections.js");
17727 if($Level eq "Join")
17728 {
17729 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17730 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017731 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017732 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17733 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 +040017734 my ($BSummary, $BMetaData) = get_Summary("Binary");
17735 my ($SSummary, $SMetaData) = get_Summary("Source");
17736 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 +030017737 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017738 <br/>
17739 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017740 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17741 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017742 </div>";
17743 $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>";
17744 $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 +030017745 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017746 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017747 return $Report;
17748 }
17749 else
17750 {
17751 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017752 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17753 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17754 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 +040017755 if($Level eq "Binary")
17756 {
17757 if(getArch(1) eq getArch(2)
17758 and getArch(1) ne "unknown") {
17759 $Description .= " on ".showArch(getArch(1));
17760 }
17761 }
17762 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 +030017763 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017764 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17765 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17766 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017767 $Report .= "</div>\n<br/><br/><br/>\n";
17768 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017769 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017770 return $Report;
17771 }
17772 }
17773}
17774
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017775sub getLegend()
17776{
17777 return "<br/>
17778<table class='summary'>
17779<tr>
17780 <td class='new'>added</td>
17781 <td class='passed'>compatible</td>
17782</tr>
17783<tr>
17784 <td class='warning'>warning</td>
17785 <td class='failed'>incompatible</td>
17786</tr></table>\n";
17787}
17788
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017789sub createReport()
17790{
17791 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017792 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017793 writeReport("Join", getReport("Join"));
17794 }
17795 elsif($DoubleReport)
17796 { # default
17797 writeReport("Binary", getReport("Binary"));
17798 writeReport("Source", getReport("Source"));
17799 }
17800 elsif($BinaryOnly)
17801 { # --binary
17802 writeReport("Binary", getReport("Binary"));
17803 }
17804 elsif($SourceOnly)
17805 { # --source
17806 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017807 }
17808}
17809
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017810sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017811{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017812 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017813
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017814 $Footer .= "<hr/>\n";
17815 $Footer .= "<div class='footer' align='right'>";
17816 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17817 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017818 $Footer .= "<br/>\n";
17819
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017820 return $Footer;
17821}
17822
17823sub get_Report_Problems($$)
17824{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017825 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017826
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017827 my $Report = get_Report_TypeProblems($Severity, $Level);
17828 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017829 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017830 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017831
17832 if($Severity eq "Low" or $Severity eq "Safe") {
17833 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017834 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017835
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017836 if($ReportFormat eq "html")
17837 {
17838 if($Report)
17839 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017840 if($JoinReport)
17841 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017842 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017843 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17844 }
17845 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017846 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017849 else
17850 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017851 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017852 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17853 }
17854 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017855 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017857 }
17858 }
17859 }
17860 return $Report;
17861}
17862
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017863sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017864{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017865 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030017866
17867 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
17868 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
17869 $Head .= "<head>\n";
17870 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
17871 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
17872 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
17873 $Head .= "<title>$Title</title>\n";
17874 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
17875 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
17876 $Head .= "</head>\n";
17877
17878 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017879}
17880
17881sub insertIDs($)
17882{
17883 my $Text = $_[0];
17884 while($Text=~/CONTENT_ID/)
17885 {
17886 if(int($Content_Counter)%2) {
17887 $ContentID -= 1;
17888 }
17889 $Text=~s/CONTENT_ID/c_$ContentID/;
17890 $ContentID += 1;
17891 $Content_Counter += 1;
17892 }
17893 return $Text;
17894}
17895
17896sub checkPreprocessedUnit($)
17897{
17898 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017899 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017900 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017901 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017902
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017903 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017904 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017905 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017906 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017907 chomp($Line);
17908 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017909 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017910 $CurHeader = path_format($1, $OSgroup);
17911 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017912 $CurClass = "";
17913
17914 if(index($CurHeader, $TMP_DIR)==0) {
17915 next;
17916 }
17917
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017918 if(substr($CurHeaderName, 0, 1) eq "<")
17919 { # <built-in>, <command-line>, etc.
17920 $CurHeaderName = "";
17921 $CurHeader = "";
17922 }
17923
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017924 if($ExtraInfo)
17925 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017926 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017927 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17928 }
17929 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017930 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017931 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017932 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017933 if($CurHeaderName)
17934 {
17935 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17936 and not $Registered_Headers{$Version}{$CurHeader})
17937 { # not a target
17938 next;
17939 }
17940 if(not is_target_header($CurHeaderName, 1)
17941 and not is_target_header($CurHeaderName, 2))
17942 { # user-defined header
17943 next;
17944 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017945 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017946 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017947
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017948 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017949 {
17950 my ($Name, $Value) = ($1, $2);
17951 if(not $Constants{$Version}{$Name}{"Access"})
17952 {
17953 $Constants{$Version}{$Name}{"Access"} = "public";
17954 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017955 if($CurHeaderName) {
17956 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17957 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017958 }
17959 }
17960 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17961 $Constants{$Version}{$1}{"Access"} = "private";
17962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017963 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017964 else
17965 {
17966 if(defined $ExtraDump)
17967 {
17968 if($Line=~/(\w+)\s*\(/)
17969 { # functions
17970 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17971 }
17972 #elsif($Line=~/(\w+)\s*;/)
17973 #{ # data
17974 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17975 #}
17976 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17977 $CurClass = $2;
17978 }
17979 }
17980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017981 }
17982 close(PREPROC);
17983 foreach my $Constant (keys(%{$Constants{$Version}}))
17984 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017985 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17986 {
17987 delete($Constants{$Version}{$Constant});
17988 next;
17989 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017990 if(not $ExtraDump and ($Constant=~/_h\Z/i
17991 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017992 { # skip
17993 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017994 }
17995 else {
17996 delete($Constants{$Version}{$Constant}{"Access"});
17997 }
17998 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017999 if($Debug)
18000 {
18001 mkpath($DEBUG_PATH{$Version});
18002 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018004}
18005
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018006sub uncoverConstant($$)
18007{
18008 my ($LibVersion, $Constant) = @_;
18009 return "" if(not $LibVersion or not $Constant);
18010 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18011 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18012 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18013 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018014
18015 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018016 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018017 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18018 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018019 {
18020 push(@RecurConstant, $Constant);
18021 my $Uncovered = uncoverConstant($LibVersion, $Value);
18022 if($Uncovered ne "") {
18023 $Value = $Uncovered;
18024 }
18025 pop(@RecurConstant);
18026 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018027
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018028 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018029 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018030 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18031 }
18032 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18033}
18034
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018035sub simpleConstant($$)
18036{
18037 my ($LibVersion, $Value) = @_;
18038 if($Value=~/\W/)
18039 {
18040 my $Value_Copy = $Value;
18041 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18042 {
18043 my $Word = $1;
18044 if($Value!~/$Word\s*\(/)
18045 {
18046 my $Val = uncoverConstant($LibVersion, $Word);
18047 if($Val ne "")
18048 {
18049 $Value=~s/\b$Word\b/$Val/g;
18050 }
18051 }
18052 }
18053 }
18054 return $Value;
18055}
18056
18057sub computeValue($)
18058{
18059 my $Value = $_[0];
18060
18061 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18062 return $1;
18063 }
18064
18065 if($Value=~/\A[\d\-\+()]+\Z/) {
18066 return eval($Value);
18067 }
18068
18069 return $Value;
18070}
18071
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018072my %IgnoreConstant = map {$_=>1} (
18073 "VERSION",
18074 "VERSIONCODE",
18075 "VERNUM",
18076 "VERS_INFO",
18077 "PATCHLEVEL",
18078 "INSTALLPREFIX",
18079 "VBUILD",
18080 "VPATCH",
18081 "VMINOR",
18082 "BUILD_STRING",
18083 "BUILD_TIME",
18084 "PACKAGE_STRING",
18085 "PRODUCTION",
18086 "CONFIGURE_COMMAND",
18087 "INSTALLDIR",
18088 "BINDIR",
18089 "CONFIG_FILE_PATH",
18090 "DATADIR",
18091 "EXTENSION_DIR",
18092 "INCLUDE_PATH",
18093 "LIBDIR",
18094 "LOCALSTATEDIR",
18095 "SBINDIR",
18096 "SYSCONFDIR",
18097 "RELEASE",
18098 "SOURCE_ID",
18099 "SUBMINOR",
18100 "MINOR",
18101 "MINNOR",
18102 "MINORVERSION",
18103 "MAJOR",
18104 "MAJORVERSION",
18105 "MICRO",
18106 "MICROVERSION",
18107 "BINARY_AGE",
18108 "INTERFACE_AGE",
18109 "CORE_ABI",
18110 "PATCH",
18111 "COPYRIGHT",
18112 "TIMESTAMP",
18113 "REVISION",
18114 "PACKAGE_TAG",
18115 "PACKAGEDATE",
18116 "NUMVERSION",
18117 "Release",
18118 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018119);
18120
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018121sub constantFilter($$$)
18122{
18123 my ($Name, $Value, $Level) = @_;
18124
18125 if($Level eq "Binary")
18126 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018127 if($Name=~/_t\Z/)
18128 { # __malloc_ptr_t
18129 return 1;
18130 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018131 foreach (keys(%IgnoreConstant))
18132 {
18133 if($Name=~/(\A|_)$_(_|\Z)/)
18134 { # version
18135 return 1;
18136 }
18137 if(/\A[A-Z].*[a-z]\Z/)
18138 {
18139 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18140 { # version
18141 return 1;
18142 }
18143 }
18144 }
18145 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18146 { # version
18147 return 1;
18148 }
18149 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18150 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18151 return 1;
18152 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018153
18154 if($Value=~/\A["'].*['"]/i)
18155 { # string
18156 return 0;
18157 }
18158
18159 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18160 { # static int gcry_pth_init
18161 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018162 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018163 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018164 return 1;
18165 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018166 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018167 { # foo(p)
18168 return 1;
18169 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018170 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018171 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018172 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018173 return 1;
18174 }
18175 }
18176
18177 return 0;
18178}
18179
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018180sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018181{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018182 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018183 foreach my $Constant (keys(%{$Constants{1}}))
18184 {
18185 if($SkipConstants{1}{$Constant})
18186 { # skipped by the user
18187 next;
18188 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018189
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018190 if(my $Header = $Constants{1}{$Constant}{"Header"})
18191 {
18192 if(not is_target_header($Header, 1)
18193 and not is_target_header($Header, 2))
18194 { # user-defined header
18195 next;
18196 }
18197 }
18198 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018199 next;
18200 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018201
18202 my $Old_Value = uncoverConstant(1, $Constant);
18203
18204 if(constantFilter($Constant, $Old_Value, $Level))
18205 { # separate binary and source problems
18206 next;
18207 }
18208
18209 if(not defined $Constants{2}{$Constant}{"Value"})
18210 { # removed
18211 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18212 "Target"=>$Constant,
18213 "Old_Value"=>$Old_Value );
18214 next;
18215 }
18216
18217 if($Constants{2}{$Constant}{"Value"} eq "")
18218 { # empty value
18219 # TODO: implement a rule
18220 next;
18221 }
18222
18223 my $New_Value = uncoverConstant(2, $Constant);
18224
18225 my $Old_Value_Pure = $Old_Value;
18226 my $New_Value_Pure = $New_Value;
18227
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018228 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18229 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18230 $New_Value_Pure=~s/(\W)\s+/$1/g;
18231 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018233 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018235 if($New_Value_Pure ne $Old_Value_Pure)
18236 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018237 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18238 { # complex values
18239 next;
18240 }
18241 if(computeValue($Old_Value) eq computeValue($New_Value))
18242 { # expressions
18243 next;
18244 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018245 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18246 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18247 next;
18248 }
18249 if($Old_Value eq "0" and $New_Value eq "NULL")
18250 { # 0 => NULL
18251 next;
18252 }
18253 if($Old_Value eq "NULL" and $New_Value eq "0")
18254 { # NULL => 0
18255 next;
18256 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018257 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018258 "Target"=>$Constant,
18259 "Old_Value"=>$Old_Value,
18260 "New_Value"=>$New_Value );
18261 }
18262 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018263
18264 foreach my $Constant (keys(%{$Constants{2}}))
18265 {
18266 if(not defined $Constants{1}{$Constant}{"Value"})
18267 {
18268 if($SkipConstants{2}{$Constant})
18269 { # skipped by the user
18270 next;
18271 }
18272
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018273 if(my $Header = $Constants{2}{$Constant}{"Header"})
18274 {
18275 if(not is_target_header($Header, 1)
18276 and not is_target_header($Header, 2))
18277 { # user-defined header
18278 next;
18279 }
18280 }
18281 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018282 next;
18283 }
18284
18285 my $New_Value = uncoverConstant(2, $Constant);
18286 if(not defined $New_Value or $New_Value eq "") {
18287 next;
18288 }
18289
18290 if(constantFilter($Constant, $New_Value, $Level))
18291 { # separate binary and source problems
18292 next;
18293 }
18294
18295 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18296 "Target"=>$Constant,
18297 "New_Value"=>$New_Value );
18298 }
18299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018300}
18301
18302sub convert_integer($)
18303{
18304 my $Value = $_[0];
18305 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018306 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018307 return hex($Value);
18308 }
18309 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018310 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018311 return oct($Value);
18312 }
18313 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018314 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018315 return oct($Value);
18316 }
18317 else {
18318 return $Value;
18319 }
18320}
18321
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018322sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018323{
18324 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018325 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018326 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018327 {
18328 if($LibVersion==1)
18329 {
18330 printMsg("WARNING", "checking headers only");
18331 $CheckHeadersOnly = 1;
18332 }
18333 else {
18334 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18335 }
18336 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018337
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018338 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018339 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018340 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018341
18342 if($CheckUndefined)
18343 {
18344 my %UndefinedLibs = ();
18345
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018346 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18347
18348 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018349 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018350 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018351 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018352 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018353 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018354 if($Symbol_Library{$LibVersion}{$Symbol}
18355 or $DepSymbol_Library{$LibVersion}{$Symbol})
18356 { # exported by target library
18357 next;
18358 }
18359 if(index($Symbol, '@')!=-1)
18360 { # exported default symbol version (@@)
18361 $Symbol=~s/\@/\@\@/;
18362 if($Symbol_Library{$LibVersion}{$Symbol}
18363 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18364 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018365 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018366 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018367 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18368 $UndefinedLibs{$Path} = 1;
18369 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018370 }
18371 }
18372 }
18373 if($ExtraInfo)
18374 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018375 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018376 {
18377 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018378 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018379 foreach (@Paths)
18380 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018381 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018382 my ($Dir, $Name) = separate_path($_);
18383
18384 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018385 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018386 }
18387
18388 $Name = parse_libname($Name, "name", $OStarget);
18389 $Name=~s/\Alib//;
18390
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018391 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018392 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018393
18394 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18395 {
18396 $LibString = " -L".esc($Dir).$LibString;
18397 }
18398
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018399 writeFile($ExtraInfo."/libs-string", $LibString);
18400 }
18401 }
18402 }
18403
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018404 if($ExtraInfo) {
18405 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18406 }
18407
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018408 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018409 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018410 if($#LibPaths!=-1)
18411 {
18412 if(not keys(%{$Symbol_Library{$LibVersion}}))
18413 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018414 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018415 printMsg("WARNING", "checking headers only");
18416 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018417 }
18418 }
18419 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018420
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018421 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018422 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018423}
18424
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018425my %Prefix_Lib_Map=(
18426 # symbols for autodetecting library dependencies (by prefix)
18427 "pthread_" => ["libpthread"],
18428 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18429 "cairo_" => ["libcairo"],
18430 "gtk_" => ["libgtk-x11-2.0"],
18431 "atk_" => ["libatk-1.0"],
18432 "gdk_" => ["libgdk-x11-2.0"],
18433 "gl" => ["libGL"],
18434 "glu" => ["libGLU"],
18435 "popt" => ["libpopt"],
18436 "Py" => ["libpython"],
18437 "jpeg_" => ["libjpeg"],
18438 "BZ2_" => ["libbz2"],
18439 "Fc" => ["libfontconfig"],
18440 "Xft" => ["libXft"],
18441 "SSL_" => ["libssl"],
18442 "sem_" => ["libpthread"],
18443 "snd_" => ["libasound"],
18444 "art_" => ["libart_lgpl_2"],
18445 "dbus_g" => ["libdbus-glib-1"],
18446 "GOMP_" => ["libgomp"],
18447 "omp_" => ["libgomp"],
18448 "cms" => ["liblcms"]
18449);
18450
18451my %Pattern_Lib_Map=(
18452 "SL[a-z]" => ["libslang"]
18453);
18454
18455my %Symbol_Lib_Map=(
18456 # symbols for autodetecting library dependencies (by name)
18457 "pow" => "libm",
18458 "fmod" => "libm",
18459 "sin" => "libm",
18460 "floor" => "libm",
18461 "cos" => "libm",
18462 "dlopen" => "libdl",
18463 "deflate" => "libz",
18464 "inflate" => "libz",
18465 "move_panel" => "libpanel",
18466 "XOpenDisplay" => "libX11",
18467 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018468 "clock_gettime" => "librt",
18469 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018470);
18471
18472sub find_SymbolLibs($$)
18473{
18474 my ($LibVersion, $Symbol) = @_;
18475
18476 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18477 { # debug symbols
18478 return ();
18479 }
18480
18481 my %Paths = ();
18482
18483 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18484 {
18485 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18486 $Paths{$Path} = 1;
18487 }
18488 }
18489
18490 if(my $SymbolPrefix = getPrefix($Symbol))
18491 {
18492 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18493 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18494 }
18495
18496 if(not keys(%Paths))
18497 {
18498 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18499 {
18500 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18501 {
18502 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18503 $Paths{$Path} = 1;
18504 }
18505 }
18506 }
18507 }
18508
18509 if(not keys(%Paths))
18510 {
18511 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18512 {
18513 if($Symbol=~/\A$Prefix/)
18514 {
18515 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18516 {
18517 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18518 $Paths{$Path} = 1;
18519 }
18520 }
18521 }
18522 }
18523 }
18524
18525 if(not keys(%Paths))
18526 {
18527 if($SymbolPrefix)
18528 { # try to find a library by symbol prefix
18529 if($SymbolPrefix eq "inotify" and
18530 index($Symbol, "\@GLIBC")!=-1)
18531 {
18532 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18533 $Paths{$Path} = 1;
18534 }
18535 }
18536 else
18537 {
18538 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18539 $Paths{$Path} = 1;
18540 }
18541 }
18542 }
18543 }
18544
18545 if(my @Paths = keys(%Paths)) {
18546 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18547 }
18548 }
18549 return keys(%Paths);
18550}
18551
18552sub get_LibPath_Prefix($$)
18553{
18554 my ($LibVersion, $Prefix) = @_;
18555
18556 $Prefix = lc($Prefix);
18557 $Prefix=~s/[_]+\Z//g;
18558
18559 foreach ("-2", "2", "-1", "1", "")
18560 { # libgnome-2.so
18561 # libxml2.so
18562 # libdbus-1.so
18563 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18564 return $Path;
18565 }
18566 }
18567 return "";
18568}
18569
18570sub getPrefix($)
18571{
18572 my $Str = $_[0];
18573 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18574 { # XmuValidArea: Xmu
18575 return $1;
18576 }
18577 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18578 { # snfReadFont: snf
18579 return $1;
18580 }
18581 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18582 { # XRRTimes: XRR
18583 return $1;
18584 }
18585 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18586 { # H5HF_delete: H5
18587 return $1;
18588 }
18589 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18590 { # alarm_event_add: alarm_
18591 return $1;
18592 }
18593 elsif($Str=~/\A(([a-z])\2{1,})/i)
18594 { # ffopen
18595 return $1;
18596 }
18597 return "";
18598}
18599
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018600sub getSymbolSize($$)
18601{ # size from the shared library
18602 my ($Symbol, $LibVersion) = @_;
18603 return 0 if(not $Symbol);
18604 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18605 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18606 {
18607 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18608 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18609 {
18610 if($Size<0) {
18611 return -$Size;
18612 }
18613 }
18614 }
18615 return 0;
18616}
18617
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018618sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018619{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18620 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018621 my ($Name, $Type) = @_;
18622
18623 # single
18624 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018625 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018626 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018627 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018628 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018629
18630 # double
18631 if($Name=~/$DEFAULT_STD_PARMS/)
18632 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018633 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018634 {
18635 my ($ShortName, $FuncParams) = split_Signature($Name);
18636
18637 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18638 {
18639 if(index($FParam, "<")!=-1)
18640 {
18641 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18642 my $FParam_N = canonifyName($FParam, "T");
18643 if($FParam_N ne $FParam) {
18644 $Name=~s/\Q$FParam\E/$FParam_N/g;
18645 }
18646 }
18647 }
18648 }
18649 elsif($Type eq "T")
18650 {
18651 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18652
18653 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018654 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018655 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018656 my $FParam = $TParams[0];
18657 foreach my $Pos (1 .. $#TParams)
18658 {
18659 my $TParam = $TParams[$Pos];
18660 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18661 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18662 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018663 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018664 }
18665 }
18666 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018667 if($Type eq "S") {
18668 return formatName($Name, "S");
18669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018670 return $Name;
18671}
18672
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018673sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018674{
18675 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018676 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018677 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018678 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018679 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018680 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018681 next if($tr_name{$Symbol});
18682 $Symbol=~s/[\@\$]+(.*)\Z//;
18683 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018684 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018685 elsif(index($Symbol, "?")==0)
18686 {
18687 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018688 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018689 }
18690 else
18691 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018692 $tr_name{$Symbol} = $Symbol;
18693 $mangled_name_gcc{$Symbol} = $Symbol;
18694 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018695 }
18696 }
18697 if($#MnglNames1 > -1)
18698 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018699 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018700 foreach my $MnglName (@MnglNames1)
18701 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018702 if(my $Unmangled = pop(@UnmangledNames))
18703 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018704 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018705 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18706 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18707 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018708 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018709 and $tr_name{$MnglName}=~/vtable for (.+)/)
18710 { # bind class name and v-table symbol
18711 my $ClassName = $1;
18712 $ClassVTable{$ClassName} = $MnglName;
18713 $VTableClass{$MnglName} = $ClassName;
18714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018715 }
18716 }
18717 }
18718 if($#MnglNames2 > -1)
18719 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018720 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018721 foreach my $MnglName (@MnglNames2)
18722 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018723 if(my $Unmangled = pop(@UnmangledNames))
18724 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018725 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018726 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018728 }
18729 }
18730 return \%tr_name;
18731}
18732
18733sub link_symbol($$$)
18734{
18735 my ($Symbol, $RunWith, $Deps) = @_;
18736 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18737 return 1;
18738 }
18739 if($Deps eq "+Deps")
18740 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018741 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018742 return 1;
18743 }
18744 }
18745 return 0;
18746}
18747
18748sub link_symbol_internal($$$)
18749{
18750 my ($Symbol, $RunWith, $Where) = @_;
18751 return 0 if(not $Where or not $Symbol);
18752 if($Where->{$RunWith}{$Symbol})
18753 { # the exact match by symbol name
18754 return 1;
18755 }
18756 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18757 { # indirect symbol version, i.e.
18758 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018759 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018760 if($Where->{$RunWith}{$VSym}) {
18761 return 1;
18762 }
18763 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018764 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018765 if($Sym and $Ver)
18766 { # search for the symbol with the same version
18767 # or without version
18768 if($Where->{$RunWith}{$Sym})
18769 { # old: foo@v|foo@@v
18770 # new: foo
18771 return 1;
18772 }
18773 if($Where->{$RunWith}{$Sym."\@".$Ver})
18774 { # old: foo|foo@@v
18775 # new: foo@v
18776 return 1;
18777 }
18778 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18779 { # old: foo|foo@v
18780 # new: foo@@v
18781 return 1;
18782 }
18783 }
18784 return 0;
18785}
18786
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018787sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018788{
18789 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018790 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018791 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018792 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018793 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018794 my $NM = get_CmdPath("nm");
18795 if(not $NM) {
18796 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018797 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018798 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018799 while(<APP>)
18800 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018801 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018802 push(@Imported, $1);
18803 }
18804 }
18805 close(APP);
18806 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018807 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018808 {
18809 my $DumpBinCmd = get_CmdPath("dumpbin");
18810 if(not $DumpBinCmd) {
18811 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18812 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018813 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018814 while(<APP>)
18815 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018816 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18817 push(@Imported, $1);
18818 }
18819 }
18820 close(APP);
18821 }
18822 else
18823 {
18824 my $ReadelfCmd = get_CmdPath("readelf");
18825 if(not $ReadelfCmd) {
18826 exitStatus("Not_Found", "can't find \"readelf\"");
18827 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018828 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018829 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018830 while(<APP>)
18831 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018832 if(defined $symtab)
18833 { # do nothing with symtab
18834 if(index($_, "'.dynsym'")!=-1)
18835 { # dynamic table
18836 $symtab = undef;
18837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018838 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018839 elsif(index($_, "'.symtab'")!=-1)
18840 { # symbol table
18841 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018842 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018843 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018844 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018845 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18846 if($Ndx eq "UND")
18847 { # only imported symbols
18848 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018849 }
18850 }
18851 }
18852 close(APP);
18853 }
18854 return @Imported;
18855}
18856
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018857my %ELF_BIND = map {$_=>1} (
18858 "WEAK",
18859 "GLOBAL"
18860);
18861
18862my %ELF_TYPE = map {$_=>1} (
18863 "FUNC",
18864 "IFUNC",
18865 "OBJECT",
18866 "COMMON"
18867);
18868
18869my %ELF_VIS = map {$_=>1} (
18870 "DEFAULT",
18871 "PROTECTED"
18872);
18873
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018874sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018875{ # read the line of 'readelf' output corresponding to the symbol
18876 my @Info = split(/\s+/, $_[0]);
18877 # Num: Value Size Type Bind Vis Ndx Name
18878 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018879 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018880 shift(@Info); # spaces
18881 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018882
18883 if($#Info==7)
18884 { # UND SYMBOL (N)
18885 if($Info[7]=~/\(\d+\)/) {
18886 pop(@Info);
18887 }
18888 }
18889
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018890 if($#Info!=6)
18891 { # other lines
18892 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018893 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018894 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018895 return () if(not defined $ELF_BIND{$Info[3]});
18896 return () if(not defined $ELF_VIS{$Info[4]});
18897 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18898 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18899 return ();
18900 }
18901 if($OStarget eq "symbian")
18902 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18903 if(index($Info[6], "_._.absent_export_")!=-1)
18904 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18905 return ();
18906 }
18907 $Info[6]=~s/\@.+//g; # remove version
18908 }
18909 if(index($Info[2], "0x") == 0)
18910 { # size == 0x3d158
18911 $Info[2] = hex($Info[2]);
18912 }
18913 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018914}
18915
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018916sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018917{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018918 my ($LibVersion, $Name) = @_;
18919 return "" if(not $LibVersion or not $Name);
18920 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18921 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018922 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018923 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18924}
18925
18926sub get_LibPath_I($$)
18927{
18928 my ($LibVersion, $Name) = @_;
18929 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018930 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018931 if(-f $Name)
18932 { # absolute path
18933 return $Name;
18934 }
18935 else
18936 { # broken
18937 return "";
18938 }
18939 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018940 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018941 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018942 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018943 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018944 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018945 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018946 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018947 }
18948 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18949 { # ldconfig default paths
18950 return $DefaultPath;
18951 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018952 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018953 { # search in default linker directories
18954 # and then in all system paths
18955 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018956 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018957 }
18958 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018959 if(not defined $Cache{"checkSystemFiles"}) {
18960 checkSystemFiles();
18961 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018962 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18963 return $AllObjects[0];
18964 }
18965 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18966 {
18967 if($ShortName ne $Name)
18968 { # FIXME: check this case
18969 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18970 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018971 }
18972 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018973 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018974 # can't find
18975 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018976}
18977
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018978sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018979{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018980 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18981 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018982
18983 my $Real_Path = realpath($Lib_Path);
18984
18985 if(not $Real_Path)
18986 { # broken link
18987 return ();
18988 }
18989
18990 my $Lib_Name = get_filename($Real_Path);
18991
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018992 if($ExtraInfo)
18993 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018994 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018995 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018996 }
18997
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018998 if($IsNeededLib)
18999 {
19000 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19001 return ();
19002 }
19003 }
19004 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019005 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019006
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 push(@RecurLib, $Lib_Name);
19008 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019009 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19010
19011 if(not $IsNeededLib)
19012 { # special cases: libstdc++ and libc
19013 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19014 {
19015 if($ShortName eq "libstdc++")
19016 { # libstdc++.so.6
19017 $STDCXX_TESTING = 1;
19018 }
19019 elsif($ShortName eq "libc")
19020 { # libc-2.11.3.so
19021 $GLIBC_TESTING = 1;
19022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019023 }
19024 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019025 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019026 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019027 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019028 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019029 mkpath(get_dirname($DebugPath));
19030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 if($OStarget eq "macos")
19032 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019033 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019034 if(not $NM) {
19035 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019036 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019037 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019038 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019039 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019040 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019041 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019042 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019043 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019044 else
19045 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019046 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019048 while(<LIB>)
19049 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019050 if($CheckUndefined)
19051 {
19052 if(not $IsNeededLib)
19053 {
19054 if(/ U _([\w\$]+)\s*\Z/)
19055 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019056 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019057 next;
19058 }
19059 }
19060 }
19061
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019062 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019063 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019064 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019065 if($IsNeededLib)
19066 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019067 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019068 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019069 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19070 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019073 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019074 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019075 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19076 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019077 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19078 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019079 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019080 setLanguage($LibVersion, "C++");
19081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019083 }
19084 }
19085 }
19086 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019087
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019088 if($Deps)
19089 {
19090 if($LIB_TYPE eq "dynamic")
19091 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019092
19093 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019094 if(not $OtoolCmd) {
19095 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019096 }
19097
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019098 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19099 while(<LIB>)
19100 {
19101 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19102 and $1 ne $Lib_Path) {
19103 $NeededLib{$1} = 1;
19104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019105 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019106 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019108 }
19109 }
19110 elsif($OStarget eq "windows")
19111 { # Windows *.dll, *.lib
19112 my $DumpBinCmd = get_CmdPath("dumpbin");
19113 if(not $DumpBinCmd) {
19114 exitStatus("Not_Found", "can't find \"dumpbin\"");
19115 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019116 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019117 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019118 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019119 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019120 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019121 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019122 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019123 else
19124 { # write to pipe
19125 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019127 while(<LIB>)
19128 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19129 # 1198 4AD SetThreadToken (forwarded to ...)
19130 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019131 # 1 0 00005B30 ??0?N = ... (with pdb)
19132 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019133 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019134 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019135 { # dynamic, static and forwarded symbols
19136 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019137 if($IsNeededLib)
19138 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019139 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019140 {
19141 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19142 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019144 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019145 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 {
19147 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19148 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019149 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19150 {
19151 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19152 setLanguage($LibVersion, "C++");
19153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019155 }
19156 }
19157 }
19158 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019159
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019160 if($Deps)
19161 {
19162 if($LIB_TYPE eq "dynamic")
19163 { # dependencies
19164 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19165 while(<LIB>)
19166 {
19167 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19168 and $1 ne $Lib_Path) {
19169 $NeededLib{path_format($1, $OSgroup)} = 1;
19170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019172 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019174 }
19175 }
19176 else
19177 { # Unix; *.so, *.a
19178 # Symbian: *.dso, *.lib
19179 my $ReadelfCmd = get_CmdPath("readelf");
19180 if(not $ReadelfCmd) {
19181 exitStatus("Not_Found", "can't find \"readelf\"");
19182 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019183 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019184 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019185 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019186 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019187 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019188 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019189 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019190 else
19191 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019192 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019193 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019194 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019195 while(<LIB>)
19196 {
19197 if($LIB_TYPE eq "dynamic")
19198 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019199 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019200 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019201 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019202 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019203 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019204 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019205 # do nothing with symtab
19206 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019207 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019208 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019209 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019210 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019211 next;
19212 }
19213 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019214 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019215 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019216 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019217 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019218 if($CheckUndefined)
19219 {
19220 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019221 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019222 }
19223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019224 next;
19225 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019226 if($Bind eq "WEAK")
19227 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019228 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019229 if($Weak eq "-Weak")
19230 { # skip WEAK symbols
19231 next;
19232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019233 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019234 my $Short = $Symbol;
19235 $Short=~s/\@.+//g;
19236 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019237 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019238 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19239 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019240 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019241 if($IsNeededLib)
19242 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019243 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019244 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019245 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19246 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019249 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019251 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19252 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19253 if($Vers)
19254 {
19255 if($LIB_EXT eq "so")
19256 { # value
19257 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19258 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019261 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19262 {
19263 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19264 setLanguage($LibVersion, "C++");
19265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019267 }
19268 }
19269 }
19270 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019271
19272 if($Deps and $LIB_TYPE eq "dynamic")
19273 { # dynamic library specifics
19274 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19275 open(LIB, $Cmd." |");
19276
19277 while(<LIB>)
19278 {
19279 if(/NEEDED.+\[([^\[\]]+)\]/)
19280 { # dependencies:
19281 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19282 $NeededLib{$1} = 1;
19283 }
19284 }
19285
19286 close(LIB);
19287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019288 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019289 if($Vers)
19290 {
19291 if(not $IsNeededLib and $LIB_EXT eq "so")
19292 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019293 my %Found = ();
19294
19295 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019296 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019297 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019298 next if(index($Symbol,"\@")==-1);
19299 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019300 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019301 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019302 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019303 if($Symbol_SameValue ne $Symbol
19304 and index($Symbol_SameValue,"\@")==-1)
19305 {
19306 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019307 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019308 last;
19309 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019310 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019311 }
19312 }
19313
19314 # default
19315 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19316 {
19317 next if(defined $Found{$Symbol});
19318 next if(index($Symbol,"\@\@")==-1);
19319
19320 if($Symbol=~/\A([^\@]*)\@\@/
19321 and not $SymVer{$LibVersion}{$1})
19322 {
19323 $SymVer{$LibVersion}{$1} = $Symbol;
19324 $Found{$Symbol} = 1;
19325 }
19326 }
19327
19328 # non-default
19329 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19330 {
19331 next if(defined $Found{$Symbol});
19332 next if(index($Symbol,"\@")==-1);
19333
19334 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19335 and not $SymVer{$LibVersion}{$1})
19336 {
19337 $SymVer{$LibVersion}{$1} = $Symbol;
19338 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019339 }
19340 }
19341 }
19342 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019343 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019344 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019345 foreach my $DyLib (sort keys(%NeededLib))
19346 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019347 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19348
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019349 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19350 {
19351 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19352 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19353 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019355 }
19356 }
19357 pop(@RecurLib);
19358 return $Library_Symbol{$LibVersion};
19359}
19360
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019361sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019362{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019363 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019364 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019365 return keys(%Prefixes);
19366}
19367
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019368sub get_prefixes_I($$)
19369{
19370 foreach my $P (@{$_[0]})
19371 {
19372 my @Parts = reverse(split(/[\/\\]+/, $P));
19373 my $Name = $Parts[0];
19374 foreach (1 .. $#Parts)
19375 {
19376 $_[1]->{$Name}{$P} = 1;
19377 last if($_>4 or $Parts[$_] eq "include");
19378 $Name = $Parts[$_].$SLASH.$Name;
19379 }
19380 }
19381}
19382
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019383sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019384{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019385 $Cache{"checkSystemFiles"} = 1;
19386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019387 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019388
19389 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 {
19391 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019392
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019393 my @Files = cmd_find($DevelPath,"f");
19394 foreach my $Link (cmd_find($DevelPath,"l"))
19395 { # add symbolic links
19396 if(-f $Link) {
19397 push(@Files, $Link);
19398 }
19399 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019400
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019401 # search for headers in /usr/lib
19402 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19403 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19404 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019405
19406 # search for libraries in /usr/lib (including symbolic links)
19407 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19408 foreach my $Path (@Libs)
19409 {
19410 my $N = get_filename($Path);
19411 $SystemObjects{$N}{$Path} = 1;
19412 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019413 }
19414 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019415
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019416 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019417 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019418 next if(not -d $DevelPath);
19419 # search for all header files in the /usr/include
19420 # with or without extension (ncurses.h, QtCore, ...)
19421 push(@SysHeaders, cmd_find($DevelPath,"f"));
19422 foreach my $Link (cmd_find($DevelPath,"l"))
19423 { # add symbolic links
19424 if(-f $Link) {
19425 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019427 }
19428 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019429 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019430}
19431
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019432sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019433{
19434 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019435 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19437 {
19438 if(not -e $Dest) {
19439 exitStatus("Access_Error", "can't access \'$Dest\'");
19440 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019441 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19443 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019444 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019445 }
19446 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019447 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019448}
19449
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019450sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451{
19452 my ($Path, $LibVersion) = @_;
19453 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019454 my $Name = get_filename($Path);
19455 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019456 return 1;
19457 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019458 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019459 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19460 return 1;
19461 }
19462 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19463 {
19464 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19465 return 1;
19466 }
19467 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019468 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019469 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019470 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019471 return 1;
19472 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019473 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019474 return 1;
19475 }
19476 }
19477 return 0;
19478}
19479
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019480sub specificHeader($$)
19481{
19482 my ($Header, $Spec) = @_;
19483 my $Name = get_filename($Header);
19484
19485 if($Spec eq "windows")
19486 {# MS Windows
19487 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19488 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19489 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19490 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19491 my @Dirs = (
19492 "win32",
19493 "win64",
19494 "win",
19495 "windows",
19496 "msvcrt"
19497 ); # /gsf-win32/
19498 if(my $DIRs = join("|", @Dirs)) {
19499 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19500 }
19501 }
19502 elsif($Spec eq "macos")
19503 { # Mac OS
19504 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19505 }
19506
19507 return 0;
19508}
19509
19510sub skipAlienHeader($)
19511{
19512 my $Path = $_[0];
19513 my $Name = get_filename($Path);
19514 my $Dir = get_dirname($Path);
19515
19516 if($Tolerance=~/2/)
19517 { # 2 - skip internal headers
19518 my @Terms = (
19519 "p",
19520 "priv",
19521 "int",
19522 "impl",
19523 "implementation",
19524 "internal",
19525 "private",
19526 "old",
19527 "compat",
19528 "debug",
19529 "test",
19530 "gen"
19531 );
19532
19533 my @Dirs = (
19534 "private",
19535 "priv",
19536 "port",
19537 "impl",
19538 "internal",
19539 "detail",
19540 "details",
19541 "old",
19542 "compat",
19543 "debug",
19544 "config",
19545 "compiler",
19546 "platform",
19547 "test"
19548 );
19549
19550 if(my $TERMs = join("|", @Terms)) {
19551 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19552 }
19553 if(my $DIRs = join("|", @Dirs)) {
19554 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19555 }
19556
19557 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19558 }
19559
19560 if($Tolerance=~/1/)
19561 { # 1 - skip non-Linux headers
19562 if($OSgroup ne "windows")
19563 {
19564 if(specificHeader($Path, "windows")) {
19565 return 1;
19566 }
19567 }
19568 if($OSgroup ne "macos")
19569 {
19570 if(specificHeader($Path, "macos")) {
19571 return 1;
19572 }
19573 }
19574 }
19575
19576 # valid
19577 return 0;
19578}
19579
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019580sub skipHeader($$)
19581{
19582 my ($Path, $LibVersion) = @_;
19583 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019584 if(defined $Cache{"skipHeader"}{$Path}) {
19585 return $Cache{"skipHeader"}{$Path};
19586 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019587 if(defined $Tolerance and $Tolerance=~/1|2/)
19588 { # --tolerant
19589 if(skipAlienHeader($Path)) {
19590 return ($Cache{"skipHeader"}{$Path} = 1);
19591 }
19592 }
19593 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19594 return 0;
19595 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019596 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19597}
19598
19599sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019600{ # returns:
19601 # 1 - if header should NOT be included and checked
19602 # 2 - if header should NOT be included, but should be checked
19603 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019604 my $Name = get_filename($Path);
19605 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606 return $Kind;
19607 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019608 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19609 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019610 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019611 if(index($Path, $D)!=-1)
19612 {
19613 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19614 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019616 }
19617 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019618 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19619 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019620 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019621 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19622 {
19623 if($Name=~/$P/) {
19624 return $Kind;
19625 }
19626 if($P=~/[\/\\]/ and $Path=~/$P/) {
19627 return $Kind;
19628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019629 }
19630 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019632 return 0;
19633}
19634
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019635sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019636{
19637 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019638 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019639 { # system directory
19640 return;
19641 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019642 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019643 { # already registered
19644 return;
19645 }
19646 foreach my $Path (find_libs($Dir,"",1))
19647 {
19648 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019649 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019650 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019651 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019652 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19653}
19654
19655sub registerObject($$)
19656{
19657 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019658
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019659 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019660 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019661 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019662 {
19663 if(my $SONAME = getSONAME($Path)) {
19664 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19665 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019666 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019667 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19668 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019669 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019670
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019671 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019672 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019673 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019674 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019675 if($ObjArch ne getArch_GCC($LibVersion))
19676 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19677 $CheckedArch{$LibVersion} = 1;
19678 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 +040019679 }
19680 }
19681 }
19682}
19683
19684sub getArch_Object($)
19685{
19686 my $Path = $_[0];
19687
19688 my %MachineType = (
19689 "14C" => "x86",
19690 "8664" => "x86_64",
19691 "1C0" => "arm",
19692 "200" => "ia64"
19693 );
19694
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019695 my %ArchName = (
19696 "s390:31-bit" => "s390",
19697 "s390:64-bit" => "s390x",
19698 "powerpc:common" => "ppc32",
19699 "powerpc:common64" => "ppc64",
19700 "i386:x86-64" => "x86_64",
19701 "mips:3000" => "mips",
19702 "sparc:v8plus" => "sparcv9"
19703 );
19704
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019705 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019706 {
19707 my $DumpbinCmd = get_CmdPath("dumpbin");
19708 if(not $DumpbinCmd) {
19709 exitStatus("Not_Found", "can't find \"dumpbin\"");
19710 }
19711
19712 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19713 my $Out = `$Cmd`;
19714
19715 if($Out=~/(\w+)\smachine/)
19716 {
19717 if(my $Type = $MachineType{uc($1)})
19718 {
19719 return $Type;
19720 }
19721 }
19722 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019723 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019724 {
19725 my $ObjdumpCmd = get_CmdPath("objdump");
19726 if(not $ObjdumpCmd) {
19727 exitStatus("Not_Found", "can't find \"objdump\"");
19728 }
19729
19730 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019731
19732 if($OSgroup eq "windows") {
19733 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19734 }
19735 else {
19736 $Cmd = "LANG=$LOCALE ".$Cmd;
19737 }
19738 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019739
19740 if($Out=~/architecture:\s+([\w\-\:]+)/)
19741 {
19742 my $Arch = $1;
19743 if($Arch=~s/\:(.+)//)
19744 {
19745 my $Suffix = $1;
19746
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019747 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019748 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019749 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019750 }
19751 }
19752
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019753 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019754 $Arch = "x86";
19755 }
19756
19757 if($Arch eq "x86-64") {
19758 $Arch = "x86_64";
19759 }
19760
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019761 if($Arch eq "ia64-elf64") {
19762 $Arch = "ia64";
19763 }
19764
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019765 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019766 }
19767 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019768 elsif($OStarget=~/macos/)
19769 {
19770 my $OtoolCmd = get_CmdPath("otool");
19771 if(not $OtoolCmd) {
19772 exitStatus("Not_Found", "can't find \"otool\"");
19773 }
19774
19775 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19776 my $Out = qx/$Cmd/;
19777
19778 if($Out=~/X86_64/i) {
19779 return "x86_64";
19780 }
19781 elsif($Out=~/X86/i) {
19782 return "x86";
19783 }
19784 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019785 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019786 {
19787 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019788 # TODO
19789 }
19790
19791 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019792}
19793
19794sub getSONAME($)
19795{
19796 my $Path = $_[0];
19797 return if(not $Path);
19798 if(defined $Cache{"getSONAME"}{$Path}) {
19799 return $Cache{"getSONAME"}{$Path};
19800 }
19801 my $ObjdumpCmd = get_CmdPath("objdump");
19802 if(not $ObjdumpCmd) {
19803 exitStatus("Not_Found", "can't find \"objdump\"");
19804 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019805 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019806 if($OSgroup eq "windows") {
19807 $SonameCmd .= " | find \"SONAME\"";
19808 }
19809 else {
19810 $SonameCmd .= " | grep SONAME";
19811 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019812 if(my $SonameInfo = `$SonameCmd`)
19813 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019814 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19815 return ($Cache{"getSONAME"}{$Path} = $1);
19816 }
19817 }
19818 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019819}
19820
19821sub getSOPaths_Dest($$)
19822{
19823 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019824 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019825 return ();
19826 }
19827 if(-f $Dest)
19828 {
19829 if(not parse_libname($Dest, "name", $OStarget)) {
19830 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19831 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019832 registerObject($Dest, $LibVersion);
19833 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019834 return ($Dest);
19835 }
19836 elsif(-d $Dest)
19837 {
19838 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019839 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019840 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019841 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19842 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019843 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019844 { # all files and symlinks that match the name of a library
19845 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19846 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019847 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019848 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019849 }
19850 }
19851 }
19852 else
19853 { # search for all files and symlinks
19854 foreach my $Path (find_libs($Dest,"",""))
19855 {
19856 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019857 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019858 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019859 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019860 }
19861 if($OSgroup eq "macos")
19862 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019863 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019864 {
19865 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019866 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019867 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019868 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19869 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019870 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019871 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019872 }
19873 }
19874 }
19875 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019876 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019877 }
19878 else {
19879 return ();
19880 }
19881}
19882
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019883sub isCyclical($$)
19884{
19885 my ($Stack, $Value) = @_;
19886 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019887}
19888
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019889sub getGCC_Opts($)
19890{ # to use in module
19891 my $LibVersion = $_[0];
19892
19893 my @Opts = ();
19894
19895 if($CompilerOptions{$LibVersion})
19896 { # user-defined options
19897 push(@Opts, $CompilerOptions{$LibVersion});
19898 }
19899 if($GccOptions)
19900 { # additional
19901 push(@Opts, $GccOptions);
19902 }
19903
19904 if(@Opts) {
19905 return join(" ", @Opts);
19906 }
19907
19908 return undef;
19909}
19910
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019911sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019912{
19913 my $LibVersion = $_[0];
19914
19915 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19916 return $Cache{"getArch_GCC"}{$LibVersion};
19917 }
19918
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019919 if(not $GCC_PATH) {
19920 return undef;
19921 }
19922
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019923 my $Arch = undef;
19924
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019925 if(my $Target = get_dumpmachine($GCC_PATH))
19926 {
19927 if($Target=~/x86_64/) {
19928 $Arch = "x86_64";
19929 }
19930 elsif($Target=~/i[3-6]86/) {
19931 $Arch = "x86";
19932 }
19933 elsif($Target=~/\Aarm/i) {
19934 $Arch = "arm";
19935 }
19936 }
19937
19938 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019939 {
19940 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19941
19942 my $Cmd = $GCC_PATH." test.c -o test";
19943 if(my $Opts = getGCC_Opts($LibVersion))
19944 { # user-defined options
19945 $Cmd .= " ".$Opts;
19946 }
19947
19948 chdir($TMP_DIR);
19949 system($Cmd);
19950 chdir($ORIG_DIR);
19951
19952 $Arch = getArch_Object("$TMP_DIR/test");
19953
19954 unlink("$TMP_DIR/test.c");
19955 unlink("$TMP_DIR/test");
19956 }
19957
19958 if(not $Arch) {
19959 exitStatus("Error", "can't check ARCH type");
19960 }
19961
19962 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19963}
19964
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019965sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019966{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019967 my $LibVersion = $_[0];
19968
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019969 my $Size = undef;
19970
19971 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019972 if(my $Arch = getArch($LibVersion))
19973 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019974 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019975 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019976 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019977 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19978 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019979 }
19980 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019981
19982 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019983 {
19984 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019985
19986 my $Cmd = $GCC_PATH." -E -dD empty.h";
19987 if(my $Opts = getGCC_Opts($LibVersion))
19988 { # user-defined options
19989 $Cmd .= " ".$Opts;
19990 }
19991
19992 chdir($TMP_DIR);
19993 my $Defines = `$Cmd`;
19994 chdir($ORIG_DIR);
19995
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019996 unlink("$TMP_DIR/empty.h");
19997
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019998 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19999 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020000 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020001 }
20002 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20003 { # GCC 3
20004 my $PTRDIFF = $1;
20005 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020006 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020007 }
20008 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020009 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020010 }
20011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020012 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020013
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020014 if(not $Size) {
20015 exitStatus("Error", "can't check WORD size");
20016 }
20017
20018 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019}
20020
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020021sub getWordSize($)
20022{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020023 return $WORD_SIZE{$_[0]};
20024}
20025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020026sub majorVersion($)
20027{
20028 my $V = $_[0];
20029 return 0 if(not $V);
20030 my @VParts = split(/\./, $V);
20031 return $VParts[0];
20032}
20033
20034sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020035{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020036 my ($V1, $V2) = @_;
20037 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020038 my @V1Parts = split(/\./, $V1);
20039 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020040 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20041 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020042 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20043 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20044 }
20045 return -1 if($#V1Parts < $#V2Parts);
20046 return 1 if($#V1Parts > $#V2Parts);
20047 return 0;
20048}
20049
20050sub read_ABI_Dump($$)
20051{
20052 my ($LibVersion, $Path) = @_;
20053 return if(not $LibVersion or not -e $Path);
20054 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020055 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020056 { # input *.abi
20057 $FilePath = $Path;
20058 }
20059 else
20060 { # input *.abi.tar.gz
20061 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020062 if(not isDump_U($FilePath)) {
20063 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020066
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020067 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020068
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020069 my $Line = readLineNum($FilePath, 0);
20070 if($Line=~/xml/)
20071 { # XML format
20072 loadModule("XmlDump");
20073 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020074 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020075 else
20076 { # Perl Data::Dumper format (default)
20077 open(DUMP, $FilePath);
20078 local $/ = undef;
20079 my $Content = <DUMP>;
20080 close(DUMP);
20081
20082 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20083 { # remove temp file
20084 unlink($FilePath);
20085 }
20086 if($Content!~/};\s*\Z/) {
20087 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20088 }
20089 $ABI = eval($Content);
20090 if(not $ABI) {
20091 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020093 }
20094 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020095 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020096 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020097 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020098 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020099 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020100 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020101 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020102 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020103
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020104 if($ABI->{"PublicABI"}) {
20105 $UsedDump{$LibVersion}{"Public"} = 1;
20106 }
20107
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020108 if($ABI->{"ABI_DUMP_VERSION"})
20109 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020110 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020111 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020112 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020114 }
20115 else
20116 { # support for old ABI dumps
20117 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020118 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020119 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020120 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020121 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020122
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020123 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020124 {
20125 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 +040020126 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020127
20128 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20129 { # DWARF ABI Dump
20130 $UseConv_Real{$LibVersion}{"P"} = 1;
20131 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20132
20133 $UsedDump{$LibVersion}{"DWARF"} = 1;
20134
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020135 if(not $TargetComponent_Opt)
20136 {
20137 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20138 $TargetComponent = "module";
20139 }
20140 else {
20141 $TargetComponent = "object";
20142 }
20143 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020144 }
20145
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020146 if(not checkDump($LibVersion, "2.11"))
20147 { # old ABI dumps
20148 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020149 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020150 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020151 { # ABI dump created with --binary option
20152 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20153 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020154 else
20155 { # default
20156 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020158
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020159 if(defined $ABI->{"Mode"}
20160 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020161 { # --ext option
20162 $ExtendedCheck = 1;
20163 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020164 if($ABI->{"Extra"}) {
20165 $ExtraDump = 1;
20166 }
20167
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020168 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020169 {
20170 $UsedDump{$LibVersion}{"L"} = $Lang;
20171 setLanguage($LibVersion, $Lang);
20172 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020173 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020174 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020175 }
20176 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020177 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020178 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020179 if(not $TInfo)
20180 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020181 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020182 }
20183 my %Tid_TDid = ();
20184 foreach my $TDid (keys(%{$TInfo}))
20185 {
20186 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20187 {
20188 $MAX_ID = $Tid if($Tid>$MAX_ID);
20189 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020190 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020191 }
20192 }
20193 my %NewID = ();
20194 foreach my $Tid (keys(%Tid_TDid))
20195 {
20196 my @TDids = keys(%{$Tid_TDid{$Tid}});
20197 if($#TDids>=1)
20198 {
20199 foreach my $TDid (@TDids)
20200 {
20201 if($TDid) {
20202 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20203 }
20204 else
20205 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020206 my $ID = ++$MAX_ID;
20207
20208 $NewID{$TDid}{$Tid} = $ID;
20209 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20210 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020211 }
20212 }
20213 }
20214 else
20215 {
20216 my $TDid = $TDids[0];
20217 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20218 }
20219 }
20220 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20221 {
20222 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20223 if(defined $Info{"BaseType"})
20224 {
20225 my $Bid = $Info{"BaseType"}{"Tid"};
20226 my $BDid = $Info{"BaseType"}{"TDid"};
20227 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020228 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020229 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20230 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020232 }
20233 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020235 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020236 read_Machine_DumpInfo($ABI, $LibVersion);
20237 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020238 if(not $SymbolInfo{$LibVersion})
20239 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020240 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020241 }
20242 if(not keys(%{$SymbolInfo{$LibVersion}}))
20243 { # validation of old-version dumps
20244 if(not $ExtendedCheck) {
20245 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20246 }
20247 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020248 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020249 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020250 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020251 else
20252 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020253 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020254 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020255 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020256 }
20257 if(not $DepSymbols)
20258 { # Cannot reconstruct DepSymbols. This may result in false
20259 # positives if the old dump is for library 2. Not a problem if
20260 # old dumps are only from old libraries.
20261 $DepSymbols = {};
20262 }
20263 foreach my $Symbol (keys(%{$DepSymbols})) {
20264 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020266 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020267 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020268
20269 if(my $V = $TargetVersion{$LibVersion}) {
20270 $Descriptor{$LibVersion}{"Version"} = $V;
20271 }
20272 else {
20273 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20274 }
20275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020276 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020277 { # if not defined by -skip-types option
20278 if(defined $ABI->{"SkipTypes"})
20279 {
20280 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20281 {
20282 $SkipTypes{$LibVersion}{$TName} = 1;
20283 }
20284 }
20285 if(defined $ABI->{"OpaqueTypes"})
20286 { # support for old dumps
20287 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20288 {
20289 $SkipTypes{$LibVersion}{$TName} = 1;
20290 }
20291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020292 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020293
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020294 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020295 { # if not defined by -skip-symbols option
20296 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20297 if(not $SkipSymbols{$LibVersion})
20298 { # support for old dumps
20299 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20300 }
20301 if(not $SkipSymbols{$LibVersion})
20302 { # support for old dumps
20303 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020305 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020306 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020307
20308 if(not $TargetHeaders{$LibVersion})
20309 { # if not defined by -headers-list option
20310 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20311 }
20312
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020313 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020314 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020315 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020316
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020317 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020318 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020319 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020320
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020321 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020322 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020323
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020324 if(not checkDump($LibVersion, "2.10.1")
20325 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020326 { # support for old ABI dumps: added target headers
20327 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020328 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020329 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020330
20331 if(not $ABI->{"PublicABI"})
20332 {
20333 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20334 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20335 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020337 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020338 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020339 if(defined $ABI->{"GccConstants"})
20340 { # 3.0
20341 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20342 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20343 }
20344 }
20345
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020346 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020347 if(not $NestedNameSpaces{$LibVersion})
20348 { # support for old dumps
20349 # Cannot reconstruct NameSpaces. This may affect design
20350 # of the compatibility report.
20351 $NestedNameSpaces{$LibVersion} = {};
20352 }
20353 # target system type
20354 # needed to adopt HTML report
20355 if(not $DumpSystem)
20356 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020357 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020358 }
20359 # recreate environment
20360 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20361 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020362 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020363 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020364 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20365 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020366 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020367 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020369 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20370 {
20371 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20372 setLanguage($LibVersion, "C++");
20373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020374 }
20375 }
20376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020377 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20378 {
20379 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20380 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20381 }
20382 }
20383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020384 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020385 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020386 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020387 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020388 {
20389 if(not $Symbol_Library{$LibVersion}{$MnglName}
20390 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20391 push(@VFunc, $MnglName);
20392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020393 }
20394 }
20395 translateSymbols(@VFunc, $LibVersion);
20396 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020397 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20398
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020399 if(not checkDump($LibVersion, "3.0"))
20400 { # support for old ABI dumps
20401 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20402 {
20403 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20404 {
20405 if(ref($BaseType) eq "HASH") {
20406 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20407 }
20408 }
20409 }
20410 }
20411
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020412 if(not checkDump($LibVersion, "3.2"))
20413 { # support for old ABI dumps
20414 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20415 {
20416 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20417 {
20418 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20419 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20420 }
20421 }
20422 }
20423
20424 # repair target headers list
20425 delete($TargetHeaders{$LibVersion});
20426 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020427 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20428 }
20429 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20430 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020431 }
20432
20433 # non-target constants from anon enums
20434 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20435 {
20436 if(not $ExtraDump
20437 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20438 {
20439 delete($Constants{$LibVersion}{$Name});
20440 }
20441 }
20442 }
20443
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020444 if(not checkDump($LibVersion, "2.20"))
20445 { # support for old ABI dumps
20446 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20447 {
20448 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20449
20450 if($TType=~/Struct|Union|Enum|Typedef/)
20451 { # repair complex types first
20452 next;
20453 }
20454
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020455 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020456 {
20457 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20458 if($BType=~/Struct|Union|Enum/i)
20459 {
20460 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20461 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20462 }
20463 }
20464 }
20465 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20466 {
20467 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20468 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20469 if($TType=~/Struct|Union|Enum/) {
20470 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20471 }
20472 }
20473 }
20474
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020475 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020476 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020477 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20478 { # support for old ABI dumps < 2.0 (ACC 1.22)
20479 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20480 {
20481 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20482 {
20483 if($Access ne "public") {
20484 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20485 }
20486 }
20487 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20488 }
20489 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20490 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020491 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20492 { # support for old ABI dumps
20493 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20494 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020495 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20496 { # DWARF ABI Dumps
20497 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20498 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020499 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20500 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20501 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020502
20503 # support for old formatting of type names
20504 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20505
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020506 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20507 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020509 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20510 {
20511 if($SubId eq $TypeId)
20512 { # Fix erroneus ABI dump
20513 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20514 next;
20515 }
20516
20517 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020518 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020519 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020520 if($TInfo{"Type"} eq "MethodPtr")
20521 {
20522 if(defined $TInfo{"Param"})
20523 { # support for old ABI dumps <= 1.17
20524 if(not defined $TInfo{"Param"}{"0"})
20525 {
20526 my $Max = keys(%{$TInfo{"Param"}});
20527 foreach my $Pos (1 .. $Max) {
20528 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20529 }
20530 delete($TInfo{"Param"}{$Max});
20531 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20532 }
20533 }
20534 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020535 if($TInfo{"BaseType"} eq $TypeId)
20536 { # fix ABI dump
20537 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20538 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020539
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020540 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020541 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020542 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020543 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020544 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20545 if(not $BName)
20546 { # broken type
20547 next;
20548 }
20549 if($TInfo{"Name"} eq $BName)
20550 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020551 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020552 next;
20553 }
20554 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20555 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020556 }
20557 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020558 }
20559 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20560 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020561 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020562 }
20563 }
20564
20565 if(not checkDump($LibVersion, "2.15"))
20566 { # support for old ABI dumps
20567 my %Dups = ();
20568 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20569 {
20570 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020571 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020572 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20573 { # remove template decls
20574 delete($SymbolInfo{$LibVersion}{$InfoId});
20575 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020577 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020578 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20579 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020580 { # templates
20581 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020582 }
20583 }
20584 }
20585
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020586 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20587 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020588 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20589 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20590 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20591 { # support for old ABI dumps (< 3.1)
20592 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20593 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20594 { # add "this" first parameter
20595 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20596 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20597
20598 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20599 {
20600 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20601 foreach my $Pos (reverse(0 .. $#Pos)) {
20602 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20603 }
20604 }
20605 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20606 }
20607 }
20608
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020609 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20610 { # ABI dumps have no mangled names for C-functions
20611 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20612 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020613 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20614 { # support for old ABI dumps
20615 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20616 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020617 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20618 { # DWARF ABI Dumps
20619 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20620 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020621 }
20622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020623 $Descriptor{$LibVersion}{"Dump"} = 1;
20624}
20625
20626sub read_Machine_DumpInfo($$)
20627{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020628 my ($ABI, $LibVersion) = @_;
20629 if($ABI->{"Arch"}) {
20630 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020631 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020632 if($ABI->{"WordSize"}) {
20633 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020634 }
20635 else
20636 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020637 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020638 }
20639 if(not $WORD_SIZE{$LibVersion})
20640 { # support for old dumps (<1.23)
20641 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20642 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020643 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020644 }
20645 else
20646 {
20647 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020648 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020649 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020650 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20651 { # any "pointer"-type
20652 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020653 last;
20654 }
20655 }
20656 if($PSize)
20657 { # a pointer type size
20658 $WORD_SIZE{$LibVersion} = $PSize;
20659 }
20660 else {
20661 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20662 }
20663 }
20664 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020665 if($ABI->{"GccVersion"}) {
20666 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020667 }
20668}
20669
20670sub read_Libs_DumpInfo($$)
20671{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020672 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020673 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20674 if(not $Library_Symbol{$LibVersion})
20675 { # support for old dumps
20676 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20677 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020678 if(keys(%{$Library_Symbol{$LibVersion}})
20679 and not $DumpAPI) {
20680 $Descriptor{$LibVersion}{"Libs"} = "OK";
20681 }
20682}
20683
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020684sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020685{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020686 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020687
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020688 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020689 and not $DumpAPI) {
20690 $Descriptor{$LibVersion}{"Headers"} = "OK";
20691 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020692 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020693 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020694 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020695 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020696 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020697
20698 if(keys(%{$ABI->{"Sources"}})
20699 and not $DumpAPI) {
20700 $Descriptor{$LibVersion}{"Sources"} = "OK";
20701 }
20702 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020703 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020704 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20705 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020707}
20708
20709sub find_libs($$$)
20710{
20711 my ($Path, $Type, $MaxDepth) = @_;
20712 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020713 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020714}
20715
20716sub createDescriptor($$)
20717{
20718 my ($LibVersion, $Path) = @_;
20719 if(not $LibVersion or not $Path
20720 or not -e $Path) {
20721 return "";
20722 }
20723 if(-d $Path)
20724 { # directory with headers files and shared objects
20725 return "
20726 <version>
20727 ".$TargetVersion{$LibVersion}."
20728 </version>
20729
20730 <headers>
20731 $Path
20732 </headers>
20733
20734 <libs>
20735 $Path
20736 </libs>";
20737 }
20738 else
20739 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020740 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020741 { # standard XML-descriptor
20742 return readFile($Path);
20743 }
20744 elsif(is_header($Path, 2, $LibVersion))
20745 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020746 $CheckHeadersOnly = 1;
20747
20748 if($LibVersion==1) {
20749 $TargetVersion{$LibVersion} = "X";
20750 }
20751
20752 if($LibVersion==2) {
20753 $TargetVersion{$LibVersion} = "Y";
20754 }
20755
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020756 return "
20757 <version>
20758 ".$TargetVersion{$LibVersion}."
20759 </version>
20760
20761 <headers>
20762 $Path
20763 </headers>
20764
20765 <libs>
20766 none
20767 </libs>";
20768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020769 else
20770 { # standard XML-descriptor
20771 return readFile($Path);
20772 }
20773 }
20774}
20775
20776sub detect_lib_default_paths()
20777{
20778 my %LPaths = ();
20779 if($OSgroup eq "bsd")
20780 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020781 if(my $LdConfig = get_CmdPath("ldconfig"))
20782 {
20783 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20784 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020785 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20786 {
20787 my $Name = "lib".$1;
20788 if(not defined $LPaths{$Name}) {
20789 $LPaths{$Name} = $2;
20790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020791 }
20792 }
20793 }
20794 else {
20795 printMsg("WARNING", "can't find ldconfig");
20796 }
20797 }
20798 else
20799 {
20800 if(my $LdConfig = get_CmdPath("ldconfig"))
20801 {
20802 if($SystemRoot and $OSgroup eq "linux")
20803 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20804 if(-e $SystemRoot."/etc/ld.so.conf") {
20805 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20806 }
20807 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020808 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20809 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020810 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20811 {
20812 my ($Name, $Path) = ($1, $2);
20813 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020814 if(not defined $LPaths{$Name})
20815 { # get first element from the list of available paths
20816
20817 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20818 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20819 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20820
20821 $LPaths{$Name} = $Path;
20822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020823 }
20824 }
20825 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020826 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020827 printMsg("WARNING", "can't find ldconfig");
20828 }
20829 }
20830 return \%LPaths;
20831}
20832
20833sub detect_bin_default_paths()
20834{
20835 my $EnvPaths = $ENV{"PATH"};
20836 if($OSgroup eq "beos") {
20837 $EnvPaths.=":".$ENV{"BETOOLS"};
20838 }
20839 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020840 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020841 {
20842 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020843 next if(not $Path);
20844 if($SystemRoot
20845 and $Path=~/\A\Q$SystemRoot\E\//)
20846 { # do NOT use binaries from target system
20847 next;
20848 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020849 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020850 }
20851}
20852
20853sub detect_inc_default_paths()
20854{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020855 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020856 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020857 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020858 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020859 next if(index($Line, "/cc1plus ")!=-1);
20860
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020861 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20862 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020863 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020864 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020865 if(index($Path, "c++")!=-1
20866 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020867 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020868 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020869 if(not defined $MAIN_CPP_DIR
20870 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20871 $MAIN_CPP_DIR = $Path;
20872 }
20873 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020874 elsif(index($Path, "gcc")!=-1) {
20875 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020876 }
20877 else
20878 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020879 if($Path=~/local[\/\\]+include/)
20880 { # local paths
20881 next;
20882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020883 if($SystemRoot
20884 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20885 { # The GCC include path for user headers is not a part of the system root
20886 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20887 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20888 next;
20889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020890 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020891 }
20892 }
20893 }
20894 unlink("$TMP_DIR/empty.h");
20895 return %DPaths;
20896}
20897
20898sub detect_default_paths($)
20899{
20900 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20901 my $Search = $_[0];
20902 if($Search!~/inc/) {
20903 $HSearch = 0;
20904 }
20905 if($Search!~/lib/) {
20906 $LSearch = 0;
20907 }
20908 if($Search!~/bin/) {
20909 $BSearch = 0;
20910 }
20911 if($Search!~/gcc/) {
20912 $GSearch = 0;
20913 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020914 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020915 { # <search_headers> section of the XML descriptor
20916 # do NOT search for systems headers
20917 $HSearch = 0;
20918 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020919 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020920 { # <search_libs> section of the XML descriptor
20921 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020922 $LSearch = 0;
20923 }
20924 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20925 { # additional search paths
20926 next if($Type eq "include" and not $HSearch);
20927 next if($Type eq "lib" and not $LSearch);
20928 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020929 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020930 }
20931 if($OSgroup ne "windows")
20932 { # unix-like
20933 foreach my $Type ("include", "lib", "bin")
20934 { # automatic detection of system "devel" directories
20935 next if($Type eq "include" and not $HSearch);
20936 next if($Type eq "lib" and not $LSearch);
20937 next if($Type eq "bin" and not $BSearch);
20938 my ($UsrDir, $RootDir) = ("/usr", "/");
20939 if($SystemRoot and $Type ne "bin")
20940 { # 1. search for target headers and libraries
20941 # 2. use host commands: ldconfig, readelf, etc.
20942 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20943 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020944 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020945 if(-d $RootDir."/".$Type)
20946 { # if "/lib" is symbolic link
20947 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020948 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020949 }
20950 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020951 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020952 }
20953 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020954 if(-d $UsrDir)
20955 {
20956 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020957 if(-d $UsrDir."/".$Type)
20958 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020959 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020960 }
20961 }
20962 }
20963 }
20964 if($BSearch)
20965 {
20966 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020967 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020968 }
20969 # check environment variables
20970 if($OSgroup eq "beos")
20971 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020972 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020973 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020974 if($_ eq ".") {
20975 next;
20976 }
20977 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20978 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20979 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020980 }
20981 }
20982 if($HSearch)
20983 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020984 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20985 split(/:|;/, $ENV{"BEINCLUDES"})
20986 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020987 }
20988 if($LSearch)
20989 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020990 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20991 split(/:|;/, $ENV{"BELIBRARIES"}),
20992 split(/:|;/, $ENV{"LIBRARY_PATH"})
20993 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020994 }
20995 }
20996 if($LSearch)
20997 { # using linker to get system paths
20998 if(my $LPaths = detect_lib_default_paths())
20999 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021000 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021001 foreach my $Name (keys(%{$LPaths}))
21002 {
21003 if($SystemRoot
21004 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21005 { # wrong ldconfig configuration
21006 # check your <sysroot>/etc/ld.so.conf
21007 next;
21008 }
21009 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021010 if(my $Dir = get_dirname($LPaths->{$Name})) {
21011 $Dirs{$Dir} = 1;
21012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021013 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021014 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021015 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021016 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021017 }
21018 if($BSearch)
21019 {
21020 if($CrossGcc)
21021 { # --cross-gcc=arm-linux-gcc
21022 if(-e $CrossGcc)
21023 { # absolute or relative path
21024 $GCC_PATH = get_abs_path($CrossGcc);
21025 }
21026 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21027 { # command name
21028 $GCC_PATH = $CrossGcc;
21029 }
21030 else {
21031 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21032 }
21033 if($GCC_PATH=~/\s/) {
21034 $GCC_PATH = "\"".$GCC_PATH."\"";
21035 }
21036 }
21037 }
21038 if($GSearch)
21039 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021040 if(not $CrossGcc)
21041 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 $GCC_PATH = get_CmdPath("gcc");
21043 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021044 if(not $GCC_PATH)
21045 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021046 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021047 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021048 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021049 { # select the latest version
21050 @GCCs = sort {$b cmp $a} @GCCs;
21051 if(check_gcc($GCCs[0], "3"))
21052 {
21053 $GCC_PATH = $GCCs[0];
21054 last;
21055 }
21056 }
21057 }
21058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021059 if(not $GCC_PATH) {
21060 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21061 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021062
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021063 my $GCC_Ver = get_dumpversion($GCC_PATH);
21064 if($GCC_Ver eq "4.8")
21065 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21066 my $Info = `$GCC_PATH --version`;
21067
21068 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21069 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21070 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21071 $GCC_Ver = $2;
21072 }
21073 }
21074
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021075 if($OStarget=~/macos/)
21076 {
21077 my $Info = `$GCC_PATH --version`;
21078
21079 if($Info=~/clang/i) {
21080 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21081 }
21082 }
21083
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021084 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021085 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021086 my $GccTarget = get_dumpmachine($GCC_PATH);
21087
21088 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021089 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021090 $OStarget = "linux";
21091 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021092 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021093 elsif($GccTarget=~/symbian/)
21094 {
21095 $OStarget = "symbian";
21096 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21097 }
21098
21099 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21100
21101 # check GCC version
21102 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21103 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021104 # introduced in 4.8 and fixed in 4.8.3
21105 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.");
21106
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021107 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021108 }
21109 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021110 else {
21111 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021112 }
21113 }
21114 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021115 {
21116 # GCC standard paths
21117 if($GCC_PATH and not $NoStdInc)
21118 {
21119 my %DPaths = detect_inc_default_paths();
21120 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21121 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21122 @DefaultIncPaths = @{$DPaths{"Inc"}};
21123 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21124 }
21125
21126 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021127 my $IncPath = "/usr/include";
21128 if($SystemRoot) {
21129 $IncPath = $SystemRoot.$IncPath;
21130 }
21131 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021132 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021133 }
21134 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021135
21136 if($ExtraInfo)
21137 {
21138 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21139 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21140 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021141}
21142
21143sub getLIB_EXT($)
21144{
21145 my $Target = $_[0];
21146 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21147 return $Ext;
21148 }
21149 return $OS_LibExt{$LIB_TYPE}{"default"};
21150}
21151
21152sub getAR_EXT($)
21153{
21154 my $Target = $_[0];
21155 if(my $Ext = $OS_Archive{$Target}) {
21156 return $Ext;
21157 }
21158 return $OS_Archive{"default"};
21159}
21160
21161sub get_dumpversion($)
21162{
21163 my $Cmd = $_[0];
21164 return "" if(not $Cmd);
21165 if($Cache{"get_dumpversion"}{$Cmd}) {
21166 return $Cache{"get_dumpversion"}{$Cmd};
21167 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021168 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021169 chomp($V);
21170 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21171}
21172
21173sub get_dumpmachine($)
21174{
21175 my $Cmd = $_[0];
21176 return "" if(not $Cmd);
21177 if($Cache{"get_dumpmachine"}{$Cmd}) {
21178 return $Cache{"get_dumpmachine"}{$Cmd};
21179 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021180 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021181 chomp($Machine);
21182 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21183}
21184
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021185sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021186{
21187 my $Cmd = $_[0];
21188 return "" if(not $Cmd);
21189 my @Options = (
21190 "--version",
21191 "-help"
21192 );
21193 foreach my $Opt (@Options)
21194 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021195 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021196 if($Info) {
21197 return 1;
21198 }
21199 }
21200 return 0;
21201}
21202
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021203sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021204{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021205 my ($Cmd, $ReqVer) = @_;
21206 return 0 if(not $Cmd or not $ReqVer);
21207 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21208 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021210 if(my $GccVer = get_dumpversion($Cmd))
21211 {
21212 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21213 if(cmpVersions($GccVer, $ReqVer)>=0) {
21214 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21215 }
21216 }
21217 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021218}
21219
21220sub get_depth($)
21221{
21222 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021223 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021224 }
21225 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21226}
21227
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021228sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021229{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021230 return if($Cache{"registerGccHeaders"}); # this function should be called once
21231
21232 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021233 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021234 my @Headers = cmd_find($Path,"f");
21235 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21236 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021237 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021238 my $FileName = get_filename($HPath);
21239 if(not defined $DefaultGccHeader{$FileName})
21240 { # skip duplicated
21241 $DefaultGccHeader{$FileName} = $HPath;
21242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021243 }
21244 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021245 $Cache{"registerGccHeaders"} = 1;
21246}
21247
21248sub registerCppHeaders()
21249{
21250 return if($Cache{"registerCppHeaders"}); # this function should be called once
21251
21252 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021253 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021254 my @Headers = cmd_find($CppDir,"f");
21255 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21256 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021257 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021258 my $FileName = get_filename($Path);
21259 if(not defined $DefaultCppHeader{$FileName})
21260 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021261 $DefaultCppHeader{$FileName} = $Path;
21262 }
21263 }
21264 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021265 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021266}
21267
21268sub parse_libname($$$)
21269{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021270 return "" if(not $_[0]);
21271 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21272 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021273 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021274 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21275}
21276
21277sub parse_libname_I($$$)
21278{
21279 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021281 if($Target eq "symbian") {
21282 return parse_libname_symbian($Name, $Type);
21283 }
21284 elsif($Target eq "windows") {
21285 return parse_libname_windows($Name, $Type);
21286 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021287
21288 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021289 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021290 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021291 { # libSDL-1.2.so.0.7.1
21292 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021293 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021294 if($Type eq "name")
21295 { # libSDL-1.2
21296 # libwbxml2
21297 return $2;
21298 }
21299 elsif($Type eq "name+ext")
21300 { # libSDL-1.2.so
21301 # libwbxml2.so
21302 return $1;
21303 }
21304 elsif($Type eq "version")
21305 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021306 if(defined $7
21307 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308 { # 0.7.1
21309 return $7;
21310 }
21311 else
21312 { # libc-2.5.so (=>2.5 version)
21313 my $MV = $5;
21314 $MV=~s/\A[\-\_]+//g;
21315 return $MV;
21316 }
21317 }
21318 elsif($Type eq "short")
21319 { # libSDL
21320 # libwbxml2
21321 return $3;
21322 }
21323 elsif($Type eq "shortest")
21324 { # SDL
21325 # wbxml
21326 return shortest_name($3);
21327 }
21328 }
21329 return "";# error
21330}
21331
21332sub parse_libname_symbian($$)
21333{
21334 my ($Name, $Type) = @_;
21335 my $Ext = getLIB_EXT("symbian");
21336 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21337 { # libpthread{00010001}.dso
21338 if($Type eq "name")
21339 { # libpthread{00010001}
21340 return $2;
21341 }
21342 elsif($Type eq "name+ext")
21343 { # libpthread{00010001}.dso
21344 return $1;
21345 }
21346 elsif($Type eq "version")
21347 { # 00010001
21348 my $V = $4;
21349 $V=~s/\{(.+)\}/$1/;
21350 return $V;
21351 }
21352 elsif($Type eq "short")
21353 { # libpthread
21354 return $3;
21355 }
21356 elsif($Type eq "shortest")
21357 { # pthread
21358 return shortest_name($3);
21359 }
21360 }
21361 return "";# error
21362}
21363
21364sub parse_libname_windows($$)
21365{
21366 my ($Name, $Type) = @_;
21367 my $Ext = getLIB_EXT("windows");
21368 if($Name=~/((.+?)\.$Ext)\Z/)
21369 { # netapi32.dll
21370 if($Type eq "name")
21371 { # netapi32
21372 return $2;
21373 }
21374 elsif($Type eq "name+ext")
21375 { # netapi32.dll
21376 return $1;
21377 }
21378 elsif($Type eq "version")
21379 { # DLL version embedded
21380 # at binary-level
21381 return "";
21382 }
21383 elsif($Type eq "short")
21384 { # netapi32
21385 return $2;
21386 }
21387 elsif($Type eq "shortest")
21388 { # netapi
21389 return shortest_name($2);
21390 }
21391 }
21392 return "";# error
21393}
21394
21395sub shortest_name($)
21396{
21397 my $Name = $_[0];
21398 # remove prefix
21399 $Name=~s/\A(lib|open)//;
21400 # remove suffix
21401 $Name=~s/[\W\d_]+\Z//i;
21402 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21403 return $Name;
21404}
21405
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021406sub createSymbolsList($$$$$)
21407{
21408 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021410 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021411 prepareSymbols(1);
21412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021413 my %SymbolHeaderLib = ();
21414 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021416 # Get List
21417 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21418 {
21419 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021420 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021421 next;
21422 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021423 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021424 { # skip other symbols
21425 next;
21426 }
21427 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21428 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021429 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021430 next;
21431 }
21432 my $DyLib = $Symbol_Library{1}{$Symbol};
21433 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021434 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021435 next;
21436 }
21437 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21438 $Total+=1;
21439 }
21440 # Draw List
21441 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21442 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21443 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21444 {
21445 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21446 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021447 my %NS_Symbol = ();
21448 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021449 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021450 }
21451 foreach my $NameSpace (sort keys(%NS_Symbol))
21452 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021453 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021454 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21455 foreach my $Symbol (@SortedInterfaces)
21456 {
21457 my $SubReport = "";
21458 my $Signature = get_Signature($Symbol, 1);
21459 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021460 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021461 }
21462 if($Symbol=~/\A(_Z|\?)/)
21463 {
21464 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021465 $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 +040021466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021467 else {
21468 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21469 }
21470 }
21471 else
21472 {
21473 if($Signature) {
21474 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21475 }
21476 else {
21477 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21478 }
21479 }
21480 $SYMBOLS_LIST .= $SubReport;
21481 }
21482 }
21483 $SYMBOLS_LIST .= "<br/>\n";
21484 }
21485 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021486 # clear info
21487 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21488 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21489 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21490 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021491 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021492 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021493 my $CssStyles = readModule("Styles", "SymbolsList.css");
21494 my $JScripts = readModule("Scripts", "Sections.js");
21495 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021496 my $Title = "$LName: public symbols";
21497 my $Keywords = "$LName, API, symbols";
21498 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021499 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021500 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021501 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021502 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021503 writeFile($SaveTo, $SYMBOLS_LIST);
21504}
21505
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021506sub add_target_libs($)
21507{
21508 foreach (@{$_[0]}) {
21509 $TargetLibs{$_} = 1;
21510 }
21511}
21512
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021513sub is_target_lib($)
21514{
21515 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021516 if(not $LName) {
21517 return 0;
21518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021519 if($TargetLibraryName
21520 and $LName!~/\Q$TargetLibraryName\E/) {
21521 return 0;
21522 }
21523 if(keys(%TargetLibs)
21524 and not $TargetLibs{$LName}
21525 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21526 return 0;
21527 }
21528 return 1;
21529}
21530
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021531sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021532{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021533 my ($H, $V) = @_;
21534 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021535 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021536 if($TargetHeaders{$V}{$H}) {
21537 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021538 }
21539 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021540 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021541}
21542
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021543sub readLibs($)
21544{
21545 my $LibVersion = $_[0];
21546 if($OStarget eq "windows")
21547 { # dumpbin.exe will crash
21548 # without VS Environment
21549 check_win32_env();
21550 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021551 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021552 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021553 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021554}
21555
21556sub dump_sorting($)
21557{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021558 my $Hash = $_[0];
21559 return [] if(not $Hash);
21560 my @Keys = keys(%{$Hash});
21561 return [] if($#Keys<0);
21562 if($Keys[0]=~/\A\d+\Z/)
21563 { # numbers
21564 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021565 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021566 else
21567 { # strings
21568 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021569 }
21570}
21571
21572sub printMsg($$)
21573{
21574 my ($Type, $Msg) = @_;
21575 if($Type!~/\AINFO/) {
21576 $Msg = $Type.": ".$Msg;
21577 }
21578 if($Type!~/_C\Z/) {
21579 $Msg .= "\n";
21580 }
21581 if($Quiet)
21582 { # --quiet option
21583 appendFile($COMMON_LOG_PATH, $Msg);
21584 }
21585 else
21586 {
21587 if($Type eq "ERROR") {
21588 print STDERR $Msg;
21589 }
21590 else {
21591 print $Msg;
21592 }
21593 }
21594}
21595
21596sub exitStatus($$)
21597{
21598 my ($Code, $Msg) = @_;
21599 printMsg("ERROR", $Msg);
21600 exit($ERROR_CODE{$Code});
21601}
21602
21603sub exitReport()
21604{ # the tool has run without any errors
21605 printReport();
21606 if($COMPILE_ERRORS)
21607 { # errors in headers may add false positives/negatives
21608 exit($ERROR_CODE{"Compile_Error"});
21609 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021610 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21611 { # --binary
21612 exit($ERROR_CODE{"Incompatible"});
21613 }
21614 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21615 { # --source
21616 exit($ERROR_CODE{"Incompatible"});
21617 }
21618 elsif($RESULT{"Source"}{"Problems"}
21619 or $RESULT{"Binary"}{"Problems"})
21620 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021621 exit($ERROR_CODE{"Incompatible"});
21622 }
21623 else {
21624 exit($ERROR_CODE{"Compatible"});
21625 }
21626}
21627
21628sub readRules($)
21629{
21630 my $Kind = $_[0];
21631 if(not -f $RULES_PATH{$Kind}) {
21632 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21633 }
21634 my $Content = readFile($RULES_PATH{$Kind});
21635 while(my $Rule = parseTag(\$Content, "rule"))
21636 {
21637 my $RId = parseTag(\$Rule, "id");
21638 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21639 foreach my $Prop (@Properties) {
21640 if(my $Value = parseTag(\$Rule, lc($Prop)))
21641 {
21642 $Value=~s/\n[ ]*//;
21643 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21644 }
21645 }
21646 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21647 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21648 }
21649 else {
21650 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21651 }
21652 }
21653}
21654
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021655sub getReportPath($)
21656{
21657 my $Level = $_[0];
21658 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21659 if($Level eq "Binary")
21660 {
21661 if($BinaryReportPath)
21662 { # --bin-report-path
21663 return $BinaryReportPath;
21664 }
21665 elsif($OutputReportPath)
21666 { # --report-path
21667 return $OutputReportPath;
21668 }
21669 else
21670 { # default
21671 return $Dir."/abi_compat_report.$ReportFormat";
21672 }
21673 }
21674 elsif($Level eq "Source")
21675 {
21676 if($SourceReportPath)
21677 { # --src-report-path
21678 return $SourceReportPath;
21679 }
21680 elsif($OutputReportPath)
21681 { # --report-path
21682 return $OutputReportPath;
21683 }
21684 else
21685 { # default
21686 return $Dir."/src_compat_report.$ReportFormat";
21687 }
21688 }
21689 else
21690 {
21691 if($OutputReportPath)
21692 { # --report-path
21693 return $OutputReportPath;
21694 }
21695 else
21696 { # default
21697 return $Dir."/compat_report.$ReportFormat";
21698 }
21699 }
21700}
21701
21702sub printStatMsg($)
21703{
21704 my $Level = $_[0];
21705 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21706}
21707
21708sub listAffected($)
21709{
21710 my $Level = $_[0];
21711 my $List = "";
21712 foreach (keys(%{$TotalAffected{$Level}}))
21713 {
21714 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21715 { # skip "Low"-severity problems
21716 next;
21717 }
21718 $List .= "$_\n";
21719 }
21720 my $Dir = get_dirname(getReportPath($Level));
21721 if($Level eq "Binary") {
21722 writeFile($Dir."/abi_affected.txt", $List);
21723 }
21724 elsif($Level eq "Source") {
21725 writeFile($Dir."/src_affected.txt", $List);
21726 }
21727}
21728
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021729sub printReport()
21730{
21731 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021732 createReport();
21733 if($JoinReport or $DoubleReport)
21734 {
21735 if($RESULT{"Binary"}{"Problems"}
21736 or $RESULT{"Source"}{"Problems"}) {
21737 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021738 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021739 else {
21740 printMsg("INFO", "result: COMPATIBLE");
21741 }
21742 printStatMsg("Binary");
21743 printStatMsg("Source");
21744 if($ListAffected)
21745 { # --list-affected
21746 listAffected("Binary");
21747 listAffected("Source");
21748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021750 elsif($BinaryOnly)
21751 {
21752 if($RESULT{"Binary"}{"Problems"}) {
21753 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21754 }
21755 else {
21756 printMsg("INFO", "result: COMPATIBLE");
21757 }
21758 printStatMsg("Binary");
21759 if($ListAffected)
21760 { # --list-affected
21761 listAffected("Binary");
21762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021763 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021764 elsif($SourceOnly)
21765 {
21766 if($RESULT{"Source"}{"Problems"}) {
21767 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21768 }
21769 else {
21770 printMsg("INFO", "result: COMPATIBLE");
21771 }
21772 printStatMsg("Source");
21773 if($ListAffected)
21774 { # --list-affected
21775 listAffected("Source");
21776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021778 if($StdOut)
21779 {
21780 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021781 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021782 printMsg("INFO", "compatibility report has been generated to stdout");
21783 }
21784 else
21785 { # default
21786 printMsg("INFO", "compatibility reports have been generated to stdout");
21787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021788 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021789 else
21790 {
21791 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021792 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021793 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21794 }
21795 elsif($DoubleReport)
21796 { # default
21797 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21798 }
21799 elsif($BinaryOnly)
21800 { # --binary
21801 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21802 }
21803 elsif($SourceOnly)
21804 { # --source
21805 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021807 }
21808}
21809
21810sub check_win32_env()
21811{
21812 if(not $ENV{"DevEnvDir"}
21813 or not $ENV{"LIB"}) {
21814 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21815 }
21816}
21817
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021818sub diffSets($$)
21819{
21820 my ($S1, $S2) = @_;
21821 my @SK1 = keys(%{$S1});
21822 my @SK2 = keys(%{$S2});
21823 if($#SK1!=$#SK2) {
21824 return 1;
21825 }
21826 foreach my $K1 (@SK1)
21827 {
21828 if(not defined $S2->{$K1}) {
21829 return 1;
21830 }
21831 }
21832 return 0;
21833}
21834
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021835sub defaultDumpPath($$)
21836{
21837 my ($N, $V) = @_;
21838 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21839}
21840
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021841sub create_ABI_Dump()
21842{
21843 if(not -e $DumpAPI) {
21844 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21845 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021846
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021847 if(isDump($DumpAPI)) {
21848 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021849 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021850 else {
21851 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021852 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021853
21854 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021855 { # set to default: N
21856 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021857 }
21858
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021859 initLogging(1);
21860 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021861
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021862 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021863 if($OutputDumpPath)
21864 { # user defined path
21865 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021866 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021867 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21868
21869 if(not $Archive and not $StdOut)
21870 { # check archive utilities
21871 if($OSgroup eq "windows")
21872 { # using zip
21873 my $ZipCmd = get_CmdPath("zip");
21874 if(not $ZipCmd) {
21875 exitStatus("Not_Found", "can't find \"zip\"");
21876 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021877 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021878 else
21879 { # using tar and gzip
21880 my $TarCmd = get_CmdPath("tar");
21881 if(not $TarCmd) {
21882 exitStatus("Not_Found", "can't find \"tar\"");
21883 }
21884 my $GzipCmd = get_CmdPath("gzip");
21885 if(not $GzipCmd) {
21886 exitStatus("Not_Found", "can't find \"gzip\"");
21887 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021888 }
21889 }
21890
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021891 if(not $Descriptor{1}{"Dump"})
21892 {
21893 if(not $CheckHeadersOnly) {
21894 readLibs(1);
21895 }
21896 if($CheckHeadersOnly) {
21897 setLanguage(1, "C++");
21898 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021899 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021900 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021901 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021902 if(not $Descriptor{1}{"Dump"})
21903 {
21904 if($Descriptor{1}{"Headers"}) {
21905 readHeaders(1);
21906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021907 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021908 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021909 if(not keys(%{$SymbolInfo{1}}))
21910 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021911 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021912 {
21913 if($CheckHeadersOnly) {
21914 exitStatus("Empty_Set", "the set of public symbols is empty");
21915 }
21916 else {
21917 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21918 }
21919 }
21920 }
21921 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021922 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021923 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21924 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021925 if($ExtraDump)
21926 { # add unmangled names to the ABI dump
21927 my @Names = ();
21928 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21929 {
21930 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21931 push(@Names, $MnglName);
21932 }
21933 }
21934 translateSymbols(@Names, 1);
21935 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21936 {
21937 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21938 {
21939 if(my $Unmangled = $tr_name{$MnglName})
21940 {
21941 if($MnglName ne $Unmangled) {
21942 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21943 }
21944 }
21945 }
21946 }
21947 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021948
21949 my %GccConstants = (); # built-in GCC constants
21950 foreach my $Name (keys(%{$Constants{1}}))
21951 {
21952 if(not defined $Constants{1}{$Name}{"Header"})
21953 {
21954 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21955 delete($Constants{1}{$Name});
21956 }
21957 }
21958
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021959 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021960 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021961 "TypeInfo" => $TypeInfo{1},
21962 "SymbolInfo" => $SymbolInfo{1},
21963 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021964 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021965 "SymbolVersion" => $SymVer{1},
21966 "LibraryVersion" => $Descriptor{1}{"Version"},
21967 "LibraryName" => $TargetLibraryName,
21968 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021969 "SkipTypes" => $SkipTypes{1},
21970 "SkipSymbols" => $SkipSymbols{1},
21971 "SkipNameSpaces" => $SkipNameSpaces{1},
21972 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021973 "Headers" => \%HeadersInfo,
21974 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021975 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021976 "NameSpaces" => $NestedNameSpaces{1},
21977 "Target" => $OStarget,
21978 "Arch" => getArch(1),
21979 "WordSize" => $WORD_SIZE{1},
21980 "GccVersion" => get_dumpversion($GCC_PATH),
21981 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21982 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21983 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021984 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021985 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021986 }
21987 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021988 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021990 if($ExtendedCheck)
21991 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021992 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021993 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021994 if($BinaryOnly)
21995 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021996 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021997 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021998 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021999 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022000 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022001 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22002 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022003 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022004
22005 my $ABI_DUMP = "";
22006 if($UseXML)
22007 {
22008 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022009 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022010 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022011 else
22012 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022013 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022015 if($StdOut)
22016 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022017 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022018 printMsg("INFO", "ABI dump has been generated to stdout");
22019 return;
22020 }
22021 else
22022 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022023 my ($DDir, $DName) = separate_path($DumpPath);
22024 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022025 if(not $Archive) {
22026 $DPath = $DumpPath;
22027 }
22028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022029 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022030
22031 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022032 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022033 close(DUMP);
22034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022035 if(not -s $DPath) {
22036 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22037 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022038 if($Archive) {
22039 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022040 }
22041
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022042 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022043 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022044 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022045 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022046 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022047 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022048 # 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 +040022049 }
22050}
22051
22052sub quickEmptyReports()
22053{ # Quick "empty" reports
22054 # 4 times faster than merging equal dumps
22055 # NOTE: the dump contains the "LibraryVersion" attribute
22056 # if you change the version, then your dump will be different
22057 # OVERCOME: use -v1 and v2 options for comparing dumps
22058 # and don't change version in the XML descriptor (and dumps)
22059 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22060 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22061 {
22062 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
22063 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
22064 if($FilePath1 and $FilePath2)
22065 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022066 my $Line = readLineNum($FilePath1, 0);
22067 if($Line=~/xml/)
22068 { # XML format
22069 # is not supported yet
22070 return;
22071 }
22072
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022073 local $/ = undef;
22074
22075 open(DUMP1, $FilePath1);
22076 my $Content1 = <DUMP1>;
22077 close(DUMP1);
22078
22079 open(DUMP2, $FilePath2);
22080 my $Content2 = <DUMP2>;
22081 close(DUMP2);
22082
22083 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022084 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022085 # clean memory
22086 undef $Content2;
22087
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022088 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022089 my $ABIdump = eval($Content1);
22090
22091 # clean memory
22092 undef $Content1;
22093
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022094 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022095 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 +040022096 }
22097 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022098 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022099 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22100 }
22101 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022102 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022103 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22104 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022105 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022106 read_Libs_DumpInfo($ABIdump, 1);
22107 read_Machine_DumpInfo($ABIdump, 1);
22108 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022109
22110 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22111 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22112
22113 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
22114 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
22115
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022116 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22117 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22118 exitReport();
22119 }
22120 }
22121 }
22122}
22123
22124sub initLogging($)
22125{
22126 my $LibVersion = $_[0];
22127 # create log directory
22128 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22129 if($OutputLogPath{$LibVersion})
22130 { # user-defined by -log-path option
22131 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22132 }
22133 if($LogMode ne "n") {
22134 mkpath($LOG_DIR);
22135 }
22136 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022137 if($Debug)
22138 { # debug directory
22139 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022140
22141 if(not $ExtraInfo)
22142 { # enable --extra-info
22143 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22144 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022145 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022146 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022147}
22148
22149sub writeLog($$)
22150{
22151 my ($LibVersion, $Msg) = @_;
22152 if($LogMode ne "n") {
22153 appendFile($LOG_PATH{$LibVersion}, $Msg);
22154 }
22155}
22156
22157sub resetLogging($)
22158{
22159 my $LibVersion = $_[0];
22160 if($LogMode!~/a|n/)
22161 { # remove old log
22162 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022163 if($Debug) {
22164 rmtree($DEBUG_PATH{$LibVersion});
22165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022166 }
22167}
22168
22169sub printErrorLog($)
22170{
22171 my $LibVersion = $_[0];
22172 if($LogMode ne "n") {
22173 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22174 }
22175}
22176
22177sub isDump($)
22178{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022179 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22180 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022181 return $1;
22182 }
22183 return 0;
22184}
22185
22186sub isDump_U($)
22187{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022188 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022189 return $1;
22190 }
22191 return 0;
22192}
22193
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022194sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022195{
22196 # read input XML descriptors or ABI dumps
22197 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022198 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022199 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022200 if(not -e $Descriptor{1}{"Path"}) {
22201 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022202 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022203
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022204 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022205 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022206 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022207 if(not -e $Descriptor{2}{"Path"}) {
22208 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022209 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022211 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022212 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022213 and isDump($Descriptor{2}{"Path"}))
22214 { # optimization: equal ABI dumps
22215 quickEmptyReports();
22216 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022217
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022218 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022219
22220 if(isDump($Descriptor{1}{"Path"})) {
22221 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022222 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022223 else {
22224 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22225 }
22226
22227 if(isDump($Descriptor{2}{"Path"})) {
22228 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22229 }
22230 else {
22231 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022232 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022233
22234 if(not $Descriptor{1}{"Version"})
22235 { # set to default: X
22236 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022237 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022238 }
22239
22240 if(not $Descriptor{2}{"Version"})
22241 { # set to default: Y
22242 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022243 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022244 }
22245
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022246 if(not $UsedDump{1}{"V"}) {
22247 initLogging(1);
22248 }
22249
22250 if(not $UsedDump{2}{"V"}) {
22251 initLogging(2);
22252 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022253
22254 # check input data
22255 if(not $Descriptor{1}{"Headers"}) {
22256 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022257 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022258 if(not $Descriptor{2}{"Headers"}) {
22259 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022260 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022261
22262 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022263 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022264 if(not $Descriptor{1}{"Libs"}) {
22265 exitStatus("Error", "can't find libraries info in descriptor d1");
22266 }
22267 if(not $Descriptor{2}{"Libs"}) {
22268 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022269 }
22270 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022271
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022272 if($UseDumps)
22273 { # --use-dumps
22274 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022275 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22276 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022277
22278 unlink($DumpPath1);
22279 unlink($DumpPath2);
22280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022281 my $pid = fork();
22282 if($pid)
22283 { # dump on two CPU cores
22284 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22285 if($RelativeDirectory{1}) {
22286 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22287 }
22288 if($OutputLogPath{1}) {
22289 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22290 }
22291 if($CrossGcc) {
22292 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22293 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022294 if($Quiet)
22295 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022296 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022297 @PARAMS = (@PARAMS, "-logging-mode", "a");
22298 }
22299 elsif($LogMode and $LogMode ne "w")
22300 { # "w" is default
22301 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022302 }
22303 if($ExtendedCheck) {
22304 @PARAMS = (@PARAMS, "-extended");
22305 }
22306 if($UserLang) {
22307 @PARAMS = (@PARAMS, "-lang", $UserLang);
22308 }
22309 if($TargetVersion{1}) {
22310 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022312 if($BinaryOnly) {
22313 @PARAMS = (@PARAMS, "-binary");
22314 }
22315 if($SourceOnly) {
22316 @PARAMS = (@PARAMS, "-source");
22317 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022318 if($SortDump) {
22319 @PARAMS = (@PARAMS, "-sort");
22320 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022321 if($DumpFormat and $DumpFormat ne "perl") {
22322 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22323 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022324 if($CheckHeadersOnly) {
22325 @PARAMS = (@PARAMS, "-headers-only");
22326 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022327 if($Debug)
22328 {
22329 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022330 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022332 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022333 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022334 exit(1);
22335 }
22336 }
22337 else
22338 { # child
22339 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22340 if($RelativeDirectory{2}) {
22341 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22342 }
22343 if($OutputLogPath{2}) {
22344 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22345 }
22346 if($CrossGcc) {
22347 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22348 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022349 if($Quiet)
22350 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022351 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022352 @PARAMS = (@PARAMS, "-logging-mode", "a");
22353 }
22354 elsif($LogMode and $LogMode ne "w")
22355 { # "w" is default
22356 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022357 }
22358 if($ExtendedCheck) {
22359 @PARAMS = (@PARAMS, "-extended");
22360 }
22361 if($UserLang) {
22362 @PARAMS = (@PARAMS, "-lang", $UserLang);
22363 }
22364 if($TargetVersion{2}) {
22365 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22366 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022367 if($BinaryOnly) {
22368 @PARAMS = (@PARAMS, "-binary");
22369 }
22370 if($SourceOnly) {
22371 @PARAMS = (@PARAMS, "-source");
22372 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022373 if($SortDump) {
22374 @PARAMS = (@PARAMS, "-sort");
22375 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022376 if($DumpFormat and $DumpFormat ne "perl") {
22377 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22378 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022379 if($CheckHeadersOnly) {
22380 @PARAMS = (@PARAMS, "-headers-only");
22381 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022382 if($Debug)
22383 {
22384 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022385 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022387 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022388 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022389 exit(1);
22390 }
22391 else {
22392 exit(0);
22393 }
22394 }
22395 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022397 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022398 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22399 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022400 if($TargetTitle ne $TargetLibraryName) {
22401 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022402 }
22403 if($ShowRetVal) {
22404 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22405 }
22406 if($CrossGcc) {
22407 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22408 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022409 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22410 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022411 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022412 }
22413 if($ReportFormat and $ReportFormat ne "html")
22414 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022415 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22416 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022417 if($OutputReportPath) {
22418 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22419 }
22420 if($BinaryReportPath) {
22421 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22422 }
22423 if($SourceReportPath) {
22424 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22425 }
22426 if($LoggingPath) {
22427 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22428 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022429 if($CheckHeadersOnly) {
22430 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22431 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022432 if($BinaryOnly) {
22433 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22434 }
22435 if($SourceOnly) {
22436 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22437 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022438 if($Debug)
22439 {
22440 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22441 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022443 system("perl", $0, @CMP_PARAMS);
22444 exit($?>>8);
22445 }
22446 if(not $Descriptor{1}{"Dump"}
22447 or not $Descriptor{2}{"Dump"})
22448 { # need GCC toolchain to analyze
22449 # header files and libraries
22450 detect_default_paths("inc|lib|gcc");
22451 }
22452 if(not $Descriptor{1}{"Dump"})
22453 {
22454 if(not $CheckHeadersOnly) {
22455 readLibs(1);
22456 }
22457 if($CheckHeadersOnly) {
22458 setLanguage(1, "C++");
22459 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022460 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022461 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022462 }
22463 if(not $Descriptor{2}{"Dump"})
22464 {
22465 if(not $CheckHeadersOnly) {
22466 readLibs(2);
22467 }
22468 if($CheckHeadersOnly) {
22469 setLanguage(2, "C++");
22470 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022471 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022472 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022473 }
22474 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22475 { # support for old ABI dumps
22476 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022477 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022478 {
22479 $WORD_SIZE{1} = $WORD_SIZE{2};
22480 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022482 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022483 {
22484 $WORD_SIZE{2} = $WORD_SIZE{1};
22485 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22486 }
22487 }
22488 elsif(not $WORD_SIZE{1}
22489 and not $WORD_SIZE{2})
22490 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022491 $WORD_SIZE{1} = "4";
22492 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022493 }
22494 if($Descriptor{1}{"Dump"})
22495 { # support for old ABI dumps
22496 prepareTypes(1);
22497 }
22498 if($Descriptor{2}{"Dump"})
22499 { # support for old ABI dumps
22500 prepareTypes(2);
22501 }
22502 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22503 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22504 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022505 # process input data
22506 if($Descriptor{1}{"Headers"}
22507 and not $Descriptor{1}{"Dump"}) {
22508 readHeaders(1);
22509 }
22510 if($Descriptor{2}{"Headers"}
22511 and not $Descriptor{2}{"Dump"}) {
22512 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022513 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022514
22515 # clean memory
22516 %SystemHeaders = ();
22517 %mangled_name_gcc = ();
22518
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022519 prepareSymbols(1);
22520 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022521
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022522 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022523 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022524
22525 # Virtual Tables
22526 registerVTable(1);
22527 registerVTable(2);
22528
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022529 if(not checkDump(1, "1.22")
22530 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022531 { # support for old ABI dumps
22532 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22533 {
22534 if($ClassName=~/</)
22535 { # templates
22536 if(not defined $VirtualTable{1}{$ClassName})
22537 { # synchronize
22538 delete($VirtualTable{2}{$ClassName});
22539 }
22540 }
22541 }
22542 }
22543
22544 registerOverriding(1);
22545 registerOverriding(2);
22546
22547 setVirtFuncPositions(1);
22548 setVirtFuncPositions(2);
22549
22550 # Other
22551 addParamNames(1);
22552 addParamNames(2);
22553
22554 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022555}
22556
22557sub compareAPIs($)
22558{
22559 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022560
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022561 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022562 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022563
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022564 if($Level eq "Binary") {
22565 printMsg("INFO", "comparing ABIs ...");
22566 }
22567 else {
22568 printMsg("INFO", "comparing APIs ...");
22569 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022570
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022571 if($CheckHeadersOnly
22572 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022573 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022574 detectAdded_H($Level);
22575 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022576 }
22577 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022578 { # added/removed in libs
22579 detectAdded($Level);
22580 detectRemoved($Level);
22581 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022582
22583 mergeSymbols($Level);
22584 if(keys(%{$CheckedSymbols{$Level}})) {
22585 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022586 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022587
22588 $Cache{"mergeTypes"} = (); # free memory
22589
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022590 if($CheckHeadersOnly
22591 or $Level eq "Source")
22592 { # added/removed in headers
22593 mergeHeaders($Level);
22594 }
22595 else
22596 { # added/removed in libs
22597 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022598 }
22599}
22600
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022601sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022602{
22603 my %Opts = (
22604 "OStarget"=>$OStarget,
22605 "Debug"=>$Debug,
22606 "Quiet"=>$Quiet,
22607 "LogMode"=>$LogMode,
22608 "CheckHeadersOnly"=>$CheckHeadersOnly,
22609
22610 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022611 "GCC_PATH"=>$GCC_PATH,
22612 "TargetSysInfo"=>$TargetSysInfo,
22613 "CrossPrefix"=>$CrossPrefix,
22614 "TargetLibraryName"=>$TargetLibraryName,
22615 "CrossGcc"=>$CrossGcc,
22616 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022617 "NoStdInc"=>$NoStdInc,
22618
22619 "BinaryOnly" => $BinaryOnly,
22620 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022621 );
22622 return \%Opts;
22623}
22624
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022625sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022626{
22627 my %CODE_ERROR = reverse(%ERROR_CODE);
22628 return $CODE_ERROR{$_[0]};
22629}
22630
22631sub scenario()
22632{
22633 if($StdOut)
22634 { # enable quiet mode
22635 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022636 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022637 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022638 if(not $LogMode)
22639 { # default
22640 $LogMode = "w";
22641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022642 if($UserLang)
22643 { # --lang=C++
22644 $UserLang = uc($UserLang);
22645 $COMMON_LANGUAGE{1}=$UserLang;
22646 $COMMON_LANGUAGE{2}=$UserLang;
22647 }
22648 if($LoggingPath)
22649 {
22650 $OutputLogPath{1} = $LoggingPath;
22651 $OutputLogPath{2} = $LoggingPath;
22652 if($Quiet) {
22653 $COMMON_LOG_PATH = $LoggingPath;
22654 }
22655 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022656
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022657 if($Quick) {
22658 $ADD_TMPL_INSTANCES = 0;
22659 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022660 if($OutputDumpPath)
22661 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022662 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022663 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22664 }
22665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022666 if($BinaryOnly and $SourceOnly)
22667 { # both --binary and --source
22668 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022669 if(not $CmpSystems)
22670 {
22671 $BinaryOnly = 0;
22672 $SourceOnly = 0;
22673 }
22674
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022675 $DoubleReport = 1;
22676 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022677
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022678 if($OutputReportPath)
22679 { # --report-path
22680 $DoubleReport = 0;
22681 $JoinReport = 1;
22682 }
22683 }
22684 elsif($BinaryOnly or $SourceOnly)
22685 { # --binary or --source
22686 $DoubleReport = 0;
22687 $JoinReport = 0;
22688 }
22689 if($UseXML)
22690 { # --xml option
22691 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022692 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022694 if($ReportFormat)
22695 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022696 $ReportFormat = lc($ReportFormat);
22697 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022698 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022699 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022700 if($ReportFormat eq "htm")
22701 { # HTM == HTML
22702 $ReportFormat = "html";
22703 }
22704 elsif($ReportFormat eq "xml")
22705 { # --report-format=XML equal to --xml
22706 $UseXML = 1;
22707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022708 }
22709 else
22710 { # default: HTML
22711 $ReportFormat = "html";
22712 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022713 if($DumpFormat)
22714 { # validate
22715 $DumpFormat = lc($DumpFormat);
22716 if($DumpFormat!~/\A(xml|perl)\Z/) {
22717 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22718 }
22719 if($DumpFormat eq "xml")
22720 { # --dump-format=XML equal to --xml
22721 $UseXML = 1;
22722 }
22723 }
22724 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022725 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022726 $DumpFormat = "perl";
22727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022728 if($Quiet and $LogMode!~/a|n/)
22729 { # --quiet log
22730 if(-f $COMMON_LOG_PATH) {
22731 unlink($COMMON_LOG_PATH);
22732 }
22733 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022734 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022735 $CheckUndefined = 1;
22736 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022737 if($TestTool and $UseDumps)
22738 { # --test && --use-dumps == --test-dump
22739 $TestDump = 1;
22740 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022741 if($Tolerant)
22742 { # enable all
22743 $Tolerance = 1234;
22744 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022745 if($Help)
22746 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022747 HELP_MESSAGE();
22748 exit(0);
22749 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022750 if($InfoMsg)
22751 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022752 INFO_MESSAGE();
22753 exit(0);
22754 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022755 if($ShowVersion)
22756 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022757 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 +040022758 exit(0);
22759 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022760 if($DumpVersion)
22761 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022762 printMsg("INFO", $TOOL_VERSION);
22763 exit(0);
22764 }
22765 if($ExtendedCheck) {
22766 $CheckHeadersOnly = 1;
22767 }
22768 if($SystemRoot_Opt)
22769 { # user defined root
22770 if(not -e $SystemRoot_Opt) {
22771 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22772 }
22773 $SystemRoot = $SystemRoot_Opt;
22774 $SystemRoot=~s/[\/]+\Z//g;
22775 if($SystemRoot) {
22776 $SystemRoot = get_abs_path($SystemRoot);
22777 }
22778 }
22779 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022780
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022781 if($SortDump)
22782 {
22783 $Data::Dumper::Useperl = 1;
22784 $Data::Dumper::Sortkeys = \&dump_sorting;
22785 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022787 if($TargetLibsPath)
22788 {
22789 if(not -f $TargetLibsPath) {
22790 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22791 }
22792 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22793 $TargetLibs{$Lib} = 1;
22794 }
22795 }
22796 if($TargetHeadersPath)
22797 { # --headers-list
22798 if(not -f $TargetHeadersPath) {
22799 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22800 }
22801 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22802 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022803 $TargetHeaders{1}{get_filename($Header)} = 1;
22804 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022805 }
22806 }
22807 if($TargetHeader)
22808 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022809 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22810 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022811 }
22812 if($TestTool
22813 or $TestDump)
22814 { # --test, --test-dump
22815 detect_default_paths("bin|gcc"); # to compile libs
22816 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022817 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022818 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022819 exit(0);
22820 }
22821 if($DumpSystem)
22822 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022823
22824 if(not $TargetSysInfo) {
22825 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22826 }
22827
22828 if(not -d $TargetSysInfo) {
22829 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22830 }
22831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022832 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022833 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022834 { # system XML descriptor
22835 if(not -f $DumpSystem) {
22836 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22837 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022838
22839 my $SDesc = readFile($DumpSystem);
22840 if(my $RelDir = $RelativeDirectory{1}) {
22841 $SDesc =~ s/{RELPATH}/$RelDir/g;
22842 }
22843
22844 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022845 foreach (@{$Ret->{"Tools"}})
22846 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022847 push_U($SystemPaths{"bin"}, $_);
22848 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022849 }
22850 if($Ret->{"CrossPrefix"}) {
22851 $CrossPrefix = $Ret->{"CrossPrefix"};
22852 }
22853 }
22854 elsif($SystemRoot_Opt)
22855 { # -sysroot "/" option
22856 # default target: /usr/lib, /usr/include
22857 # search libs: /usr/lib and /lib
22858 if(not -e $SystemRoot."/usr/lib") {
22859 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22860 }
22861 if(not -e $SystemRoot."/lib") {
22862 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22863 }
22864 if(not -e $SystemRoot."/usr/include") {
22865 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22866 }
22867 readSystemDescriptor("
22868 <name>
22869 $DumpSystem
22870 </name>
22871 <headers>
22872 $SystemRoot/usr/include
22873 </headers>
22874 <libs>
22875 $SystemRoot/usr/lib
22876 </libs>
22877 <search_libs>
22878 $SystemRoot/lib
22879 </search_libs>");
22880 }
22881 else {
22882 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22883 }
22884 detect_default_paths("bin|gcc"); # to check symbols
22885 if($OStarget eq "windows")
22886 { # to run dumpbin.exe
22887 # and undname.exe
22888 check_win32_env();
22889 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022890 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022891 exit(0);
22892 }
22893 if($CmpSystems)
22894 { # --cmp-systems
22895 detect_default_paths("bin"); # to extract dumps
22896 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022897 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022898 exit(0);
22899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022900 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022901 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022902 }
22903 else
22904 { # validate library name
22905 if($TargetLibraryName=~/[\*\/\\]/) {
22906 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22907 }
22908 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022909 if(not $TargetTitle) {
22910 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022911 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022912
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022913 if($SymbolsListPath)
22914 {
22915 if(not -f $SymbolsListPath) {
22916 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22917 }
22918 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22919 $SymbolsList{$Interface} = 1;
22920 }
22921 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022922 if($TypesListPath)
22923 {
22924 if(not -f $TypesListPath) {
22925 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22926 }
22927 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22928 $TypesList{$Type} = 1;
22929 }
22930 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022931 if($SkipSymbolsListPath)
22932 {
22933 if(not -f $SkipSymbolsListPath) {
22934 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22935 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022936 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22937 {
22938 $SkipSymbols{1}{$Interface} = 1;
22939 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022940 }
22941 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030022942 if($SkipTypesListPath)
22943 {
22944 if(not -f $SkipTypesListPath) {
22945 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
22946 }
22947 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
22948 {
22949 $SkipTypes{1}{$Type} = 1;
22950 $SkipTypes{2}{$Type} = 1;
22951 }
22952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022953 if($SkipHeadersPath)
22954 {
22955 if(not -f $SkipHeadersPath) {
22956 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22957 }
22958 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022959 { # register for both versions
22960 $SkipHeadersList{1}{$Path} = 1;
22961 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030022962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022963 my ($CPath, $Type) = classifyPath($Path);
22964 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022965 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022966 }
22967 }
22968 if($ParamNamesPath)
22969 {
22970 if(not -f $ParamNamesPath) {
22971 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22972 }
22973 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22974 {
22975 if($Line=~s/\A(\w+)\;//)
22976 {
22977 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022978 if($Line=~/;(\d+);/)
22979 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022980 while($Line=~s/(\d+);(\w+)//) {
22981 $AddIntParams{$Interface}{$1}=$2;
22982 }
22983 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022984 else
22985 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022986 my $Num = 0;
22987 foreach my $Name (split(/;/, $Line)) {
22988 $AddIntParams{$Interface}{$Num++}=$Name;
22989 }
22990 }
22991 }
22992 }
22993 }
22994 if($AppPath)
22995 {
22996 if(not -f $AppPath) {
22997 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22998 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022999
23000 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023001 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023002 $SymbolsList_App{$Interface} = 1;
23003 }
23004 }
23005 if($DumpAPI)
23006 { # --dump-abi
23007 # make an API dump
23008 create_ABI_Dump();
23009 exit($COMPILE_ERRORS);
23010 }
23011 # default: compare APIs
23012 # -d1 <path>
23013 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023014 compareInit();
23015 if($JoinReport or $DoubleReport)
23016 {
23017 compareAPIs("Binary");
23018 compareAPIs("Source");
23019 }
23020 elsif($BinaryOnly) {
23021 compareAPIs("Binary");
23022 }
23023 elsif($SourceOnly) {
23024 compareAPIs("Source");
23025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023026 exitReport();
23027}
23028
23029scenario();