blob: 650f3a14818f15ba675c6bbe0bec05db7be30e43 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03003# ABI Compliance Checker (ABICC) 1.99.17
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 Ponomarenko8a4c3f82016-02-21 03:45:16 +030063my $TOOL_VERSION = "1.99.17";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040064my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040088$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040089$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030090$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040091$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat,
93$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040095
96my $CmdName = get_filename($0);
97my %OS_LibExt = (
98 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040099 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400100 "macos"=>"dylib",
101 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "symbian"=>"dso",
103 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400104 },
105 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400106 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400107 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "symbian"=>"lib",
109 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400110 }
111);
112
113my %OS_Archive = (
114 "windows"=>"zip",
115 "default"=>"tar.gz"
116);
117
118my %ERROR_CODE = (
119 # Compatible verdict
120 "Compatible"=>0,
121 "Success"=>0,
122 # Incompatible verdict
123 "Incompatible"=>1,
124 # Undifferentiated error code
125 "Error"=>2,
126 # System command is not found
127 "Not_Found"=>3,
128 # Cannot access input files
129 "Access_Error"=>4,
130 # Cannot compile header files
131 "Cannot_Compile"=>5,
132 # Header compiled with errors
133 "Compile_Error"=>6,
134 # Invalid input ABI dump
135 "Invalid_Dump"=>7,
136 # Incompatible version of ABI dump
137 "Dump_Version"=>8,
138 # Cannot find a module
139 "Module_Error"=>9,
140 # Empty intersection between
141 # headers and shared objects
142 "Empty_Intersection"=>10,
143 # Empty set of symbols in headers
144 "Empty_Set"=>11
145);
146
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300147my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400148
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400149my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400150A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300151Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400152License: GNU LGPL or GNU GPL
153
154Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400155Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400156
157OLD.xml and NEW.xml are XML-descriptors:
158
159 <version>
160 1.0
161 </version>
162
163 <headers>
164 /path/to/headers/
165 </headers>
166
167 <libs>
168 /path/to/libraries/
169 </libs>
170
171More info: $CmdName --help\n";
172
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400173if($#ARGV==-1)
174{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400175 printMsg("INFO", $ShortUsage);
176 exit(0);
177}
178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400179GetOptions("h|help!" => \$Help,
180 "i|info!" => \$InfoMsg,
181 "v|version!" => \$ShowVersion,
182 "dumpversion!" => \$DumpVersion,
183# general options
184 "l|lib|library=s" => \$TargetLibraryName,
185 "d1|old|o=s" => \$Descriptor{1}{"Path"},
186 "d2|new|n=s" => \$Descriptor{2}{"Path"},
187 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400188# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400189 "app|application=s" => \$AppPath,
190 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400191 "gcc-path|cross-gcc=s" => \$CrossGcc,
192 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
193 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300195 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
196 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400197 "s|strict!" => \$StrictCompat,
198 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300199 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400200 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300201 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400202 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400203 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400204 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400205 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400206 "show-retval!" => \$ShowRetVal,
207 "use-dumps!" => \$UseDumps,
208 "nostdinc!" => \$NoStdInc,
209 "dump-system=s" => \$DumpSystem,
210 "sysinfo=s" => \$TargetSysInfo,
211 "cmp-systems!" => \$CmpSystems,
212 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400213 "ext|extended!" => \$ExtendedCheck,
214 "q|quiet!" => \$Quiet,
215 "stdout!" => \$StdOut,
216 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400217 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400218 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400219 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400220 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400221 "binary|bin|abi!" => \$BinaryOnly,
222 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400223 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400224# other options
225 "test!" => \$TestTool,
226 "test-dump!" => \$TestDump,
227 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400228 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400229 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "p|params=s" => \$ParamNamesPath,
231 "relpath1|relpath=s" => \$RelativeDirectory{1},
232 "relpath2=s" => \$RelativeDirectory{2},
233 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400234 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400235 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400236 "bin-report-path=s" => \$BinaryReportPath,
237 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "log-path=s" => \$LoggingPath,
239 "log1-path=s" => \$OutputLogPath{1},
240 "log2-path=s" => \$OutputLogPath{2},
241 "logging-mode=s" => \$LogMode,
242 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300243 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400244 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400245 "extra-info=s" => \$ExtraInfo,
246 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400247 "force!" => \$Force,
248 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400249 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400250 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400251 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400252 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300253 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
254 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300255 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400256) or ERR_MESSAGE();
257
258sub ERR_MESSAGE()
259{
260 printMsg("INFO", "\n".$ShortUsage);
261 exit($ERROR_CODE{"Error"});
262}
263
264my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
265my $SLIB_TYPE = $LIB_TYPE;
266if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
267{ # show as "shared" library
268 $SLIB_TYPE = "shared";
269}
270my $LIB_EXT = getLIB_EXT($OSgroup);
271my $AR_EXT = getAR_EXT($OSgroup);
272my $BYTE_SIZE = 8;
273my $COMMON_LOG_PATH = "logs/run.log";
274
275my $HelpMessage="
276NAME:
277 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400278 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400279
280DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400281 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400282 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
283 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
284 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
285 and/or source-level compatibility: changes in calling stack, v-table changes,
286 removed symbols, renamed fields, etc. Binary incompatibility may result in
287 crashing or incorrect behavior of applications built with an old version of
288 a library if they run on a new one. Source incompatibility may result in
289 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400290
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400291 The tool is intended for developers of software libraries and maintainers
292 of operating systems who are interested in ensuring backward compatibility,
293 i.e. allow old applications to run or to be recompiled with newer library
294 versions.
295
296 Also the tool can be used by ISVs for checking applications portability to
297 new library versions. Found issues can be taken into account when adapting
298 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400299
300 This tool is free software: you can redistribute it and/or modify it
301 under the terms of the GNU LGPL or GNU GPL.
302
303USAGE:
304 $CmdName [options]
305
306EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400307 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400308
309 OLD.xml and NEW.xml are XML-descriptors:
310
311 <version>
312 1.0
313 </version>
314
315 <headers>
316 /path1/to/header(s)/
317 /path2/to/header(s)/
318 ...
319 </headers>
320
321 <libs>
322 /path1/to/library(ies)/
323 /path2/to/library(ies)/
324 ...
325 </libs>
326
327INFORMATION OPTIONS:
328 -h|-help
329 Print this help.
330
331 -i|-info
332 Print complete info.
333
334 -v|-version
335 Print version information.
336
337 -dumpversion
338 Print the tool version ($TOOL_VERSION) and don't do anything else.
339
340GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400341 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400342 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400343
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400344 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400345 Descriptor of 1st (old) library version.
346 It may be one of the following:
347
348 1. XML-descriptor (VERSION.xml file):
349
350 <version>
351 1.0
352 </version>
353
354 <headers>
355 /path1/to/header(s)/
356 /path2/to/header(s)/
357 ...
358 </headers>
359
360 <libs>
361 /path1/to/library(ies)/
362 /path2/to/library(ies)/
363 ...
364 </libs>
365
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300366 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367
368 2. ABI dump generated by -dump option
369 3. Directory with headers and/or $SLIB_TYPE libraries
370 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300372 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400373 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400374
375 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400376 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400377
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400378 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400379 Descriptor of 2nd (new) library version.
380
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400381 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400382 Create library ABI dump for the input XML descriptor. You can
383 transfer it anywhere and pass instead of the descriptor. Also
384 it can be used for debugging the tool.
385
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300386 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400387
388sub HELP_MESSAGE() {
389 printMsg("INFO", $HelpMessage."
390MORE INFO:
391 $CmdName --info\n");
392}
393
394sub INFO_MESSAGE()
395{
396 printMsg("INFO", "$HelpMessage
397EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400398 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300399 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400400 for portability to the new library version.
401
402 -static-libs
403 Check static libraries instead of the shared ones. The <libs> section
404 of the XML-descriptor should point to static libraries location.
405
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300406 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400407 Path to the cross GCC compiler to use instead of the usual (host) GCC.
408
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300409 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300411
412 -gcc-options OPTS
413 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400415 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400416 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400417 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400419 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400420 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200421 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422
423 In general case you should specify it in the XML-descriptor:
424 <version>
425 VERSION
426 </version>
427
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400428 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429 Specify 2nd library version outside the descriptor.
430
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400431 -vnum NUM
432 Specify the library version in the generated ABI dump. The <version> section
433 of the input XML descriptor will be overwritten in this case.
434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 -s|-strict
436 Treat all compatibility warnings as problems. Add a number of \"Low\"
437 severity problems to the return value of the tool.
438
439 -headers-only
440 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
441 provide a low quality compatibility report with false positives and
442 without detecting of added/removed symbols.
443
444 Alternatively you can write \"none\" word to the <libs> section
445 in the XML-descriptor:
446 <libs>
447 none
448 </libs>
449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450 -show-retval
451 Show the symbol's return type in the report.
452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400453 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300454 This option allows to specify a file with a list of symbols (mangled
455 names in C++) that should be checked. Other symbols will not be checked.
456
457 -types-list PATH
458 This option allows to specify a file with a list of types that should
459 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400460
461 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300462 The list of symbols that should not be checked.
463
464 -skip-types PATH
465 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400466
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400467 -headers-list PATH
468 The file with a list of headers, that should be checked/dumped.
469
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400470 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400471 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400472
473 -header NAME
474 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400475
476 -use-dumps
477 Make dumps for two versions of a library and compare dumps. This should
478 increase the performance of the tool and decrease the system memory usage.
479
480 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400481 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400482
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400483 -dump-system NAME -sysroot DIR
484 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400485 create XML descriptors and make ABI dumps for each library. The result
486 set of ABI dumps can be compared (--cmp-systems) with the other one
487 created for other version of operating system in order to check them for
488 compatibility. Do not forget to specify -cross-gcc option if your target
489 system requires some specific version of GCC compiler (different from
490 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400491 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400492
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400493 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400494 The same as the previous option but takes an XML descriptor of the target
495 system as input, where you should describe it:
496
497 /* Primary sections */
498
499 <name>
500 /* Name of the system */
501 </name>
502
503 <headers>
504 /* The list of paths to header files and/or
505 directories with header files, one per line */
506 </headers>
507
508 <libs>
509 /* The list of paths to shared libraries and/or
510 directories with shared libraries, one per line */
511 </libs>
512
513 /* Optional sections */
514
515 <search_headers>
516 /* List of directories to be searched
517 for header files to automatically
518 generate include paths, one per line */
519 </search_headers>
520
521 <search_libs>
522 /* List of directories to be searched
523 for shared libraries to resolve
524 dependencies, one per line */
525 </search_libs>
526
527 <tools>
528 /* List of directories with tools used
529 for analysis (GCC toolchain), one per line */
530 </tools>
531
532 <cross_prefix>
533 /* GCC toolchain prefix.
534 Examples:
535 arm-linux-gnueabi
536 arm-none-symbianelf */
537 </cross_prefix>
538
539 <gcc_options>
540 /* Additional GCC options, one per line */
541 </gcc_options>
542
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400543 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300544 This option should be used with -dump-system option to dump
545 ABI of operating systems and configure the dumping process.
546 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400547 modules/Targets/{unix, symbian, windows}
548
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400549 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400550 Compare two system ABI dumps. Create compatibility reports for each
551 library and the common HTML report including the summary of test
552 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400553 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400554
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400555 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400556 The file with a list of libraries, that should be dumped by
557 the -dump-system option or should be checked by the -cmp-systems option.
558
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400559 -ext|-extended
560 If your library A is supposed to be used by other library B and you
561 want to control the ABI of B, then you should enable this option. The
562 tool will check for changes in all data types, even if they are not
563 used by any function in the library A. Such data types are not part
564 of the A library ABI, but may be a part of the ABI of the B library.
565
566 The short scheme is:
567 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
568
569 -q|-quiet
570 Print all messages to the file instead of stdout and stderr.
571 Default path (can be changed by -log-path option):
572 $COMMON_LOG_PATH
573
574 -stdout
575 Print analysis results (compatibility reports and ABI dumps) to stdout
576 instead of creating a file. This would allow piping data to other programs.
577
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400578 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400579 Change format of compatibility report.
580 Formats:
581 htm - HTML format (default)
582 xml - XML format
583
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400584 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400585 Change format of ABI dump.
586 Formats:
587 perl - Data::Dumper format (default)
588 xml - XML format
589
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400590 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400591 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400592
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400593 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400594 Set library language (C or C++). You can use this option if the tool
595 cannot auto-detect a language. This option may be useful for checking
596 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400597
598 -arch ARCH
599 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
600 ect.). The option is useful if the tool cannot detect correct architecture
601 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400602
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400603 -binary|-bin|-abi
604 Show \"Binary\" compatibility problems only.
605 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400606 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400607
608 -source|-src|-api
609 Show \"Source\" compatibility problems only.
610 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400611 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400612
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400613 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400614 The maximum number of affected symbols listed under the description
615 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400617OTHER OPTIONS:
618 -test
619 Run internal tests. Create two binary incompatible versions of a sample
620 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300621 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400622
623 -test-dump
624 Test ability to create, read and compare ABI dumps.
625
626 -debug
627 Debugging mode. Print debug info on the screen. Save intermediate
628 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400629 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400630
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631 Also consider using --dump option for debugging the tool.
632
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400633 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400634 If your header files are written in C language and can be compiled
635 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
636 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400637
638 -cpp-incompatible
639 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400640
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400641 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400642 Path to file with the function parameter names. It can be used
643 for improving report view if the library header files have no
644 parameter names. File format:
645
646 func1;param1;param2;param3 ...
647 func2;param1;param2;param3 ...
648 ...
649
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400650 -relpath PATH
651 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400652 for dumping the library ABI (see -dump option).
653
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400654 -relpath1 PATH
655 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 -relpath2 PATH
658 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400660 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400661 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400663 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400664
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400665 -sort
666 Enable sorting of data in ABI dumps.
667
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400668 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400669 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400670 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400672
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400673 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400674 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400675 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400676 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400677
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400679 Path to \"Source\" compatibility report.
680 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400682
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400684 Log path for all messages.
685 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400686 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400687
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689 Log path for 1st version of a library.
690 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694 Log path for 2nd version of a library.
695 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699 Change logging mode.
700 Modes:
701 w - overwrite old logs (default)
702 a - append old logs
703 n - do not write any logs
704
705 -list-affected
706 Generate file with the list of incompatible
707 symbols beside the HTML compatibility report.
708 Use 'c++filt \@file' command from GNU binutils
709 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400710 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400712 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400713
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 The component name in the title and summary of the HTML report.
716 Default:
717 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300718
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300719 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400722
723 -extra-info DIR
724 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400725
726 -extra-dump
727 Create extended ABI dump containing all symbols
728 from the translation unit.
729
730 -force
731 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400732
733 -tolerance LEVEL
734 Apply a set of heuristics to successfully compile input
735 header files. You can enable several tolerance levels by
736 joining them into one string (e.g. 13, 124, etc.).
737 Levels:
738 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
739 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
740 3 - skip headers that iclude non-Linux headers
741 4 - skip headers included by others
742
743 -tolerant
744 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400745
746 -check
747 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400748
749 -quick
750 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400751
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300752 -skip-internal-symbols PATTERN
753 Do not check symbols matched by the pattern.
754
755 -skip-internal-types PATTERN
756 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300757
758 -check-private-abi
759 Check data types from the private part of the ABI when
760 comparing ABI dumps created by the ABI Dumper tool with
761 use of the -public-headers option.
762
763 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400765REPORT:
766 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400767 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400768
769 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400770 logs/LIB_NAME/V1/log.txt
771 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400772
773EXIT CODES:
774 0 - Compatible. The tool has run without any errors.
775 non-zero - Incompatible or the tool has run with errors.
776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400777MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300778 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400779}
780
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400781my %Operator_Indication = (
782 "not" => "~",
783 "assign" => "=",
784 "andassign" => "&=",
785 "orassign" => "|=",
786 "xorassign" => "^=",
787 "or" => "|",
788 "xor" => "^",
789 "addr" => "&",
790 "and" => "&",
791 "lnot" => "!",
792 "eq" => "==",
793 "ne" => "!=",
794 "lt" => "<",
795 "lshift" => "<<",
796 "lshiftassign" => "<<=",
797 "rshiftassign" => ">>=",
798 "call" => "()",
799 "mod" => "%",
800 "modassign" => "%=",
801 "subs" => "[]",
802 "land" => "&&",
803 "lor" => "||",
804 "rshift" => ">>",
805 "ref" => "->",
806 "le" => "<=",
807 "deref" => "*",
808 "mult" => "*",
809 "preinc" => "++",
810 "delete" => " delete",
811 "vecnew" => " new[]",
812 "vecdelete" => " delete[]",
813 "predec" => "--",
814 "postinc" => "++",
815 "postdec" => "--",
816 "plusassign" => "+=",
817 "plus" => "+",
818 "minus" => "-",
819 "minusassign" => "-=",
820 "gt" => ">",
821 "ge" => ">=",
822 "new" => " new",
823 "multassign" => "*=",
824 "divassign" => "/=",
825 "div" => "/",
826 "neg" => "-",
827 "pos" => "+",
828 "memref" => "->*",
829 "compound" => "," );
830
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400831my %UnknownOperator;
832
833my %NodeType= (
834 "array_type" => "Array",
835 "binfo" => "Other",
836 "boolean_type" => "Intrinsic",
837 "complex_type" => "Intrinsic",
838 "const_decl" => "Other",
839 "enumeral_type" => "Enum",
840 "field_decl" => "Other",
841 "function_decl" => "Other",
842 "function_type" => "FunctionType",
843 "identifier_node" => "Other",
844 "integer_cst" => "Other",
845 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400846 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400847 "method_type" => "MethodType",
848 "namespace_decl" => "Other",
849 "parm_decl" => "Other",
850 "pointer_type" => "Pointer",
851 "real_cst" => "Other",
852 "real_type" => "Intrinsic",
853 "record_type" => "Struct",
854 "reference_type" => "Ref",
855 "string_cst" => "Other",
856 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400857 "template_type_parm" => "TemplateParam",
858 "typename_type" => "TypeName",
859 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400860 "tree_list" => "Other",
861 "tree_vec" => "Other",
862 "type_decl" => "Other",
863 "union_type" => "Union",
864 "var_decl" => "Other",
865 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400866 "nop_expr" => "Other", #
867 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400868 "offset_type" => "Other" );
869
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400870my %CppKeywords_C = map {$_=>1} (
871 # C++ 2003 keywords
872 "public",
873 "protected",
874 "private",
875 "default",
876 "template",
877 "new",
878 #"asm",
879 "dynamic_cast",
880 "auto",
881 "try",
882 "namespace",
883 "typename",
884 "using",
885 "reinterpret_cast",
886 "friend",
887 "class",
888 "virtual",
889 "const_cast",
890 "mutable",
891 "static_cast",
892 "export",
893 # C++0x keywords
894 "noexcept",
895 "nullptr",
896 "constexpr",
897 "static_assert",
898 "explicit",
899 # cannot be used as a macro name
900 # as it is an operator in C++
901 "and",
902 #"and_eq",
903 "not",
904 #"not_eq",
905 "or"
906 #"or_eq",
907 #"bitand",
908 #"bitor",
909 #"xor",
910 #"xor_eq",
911 #"compl"
912);
913
914my %CppKeywords_F = map {$_=>1} (
915 "delete",
916 "catch",
917 "alignof",
918 "thread_local",
919 "decltype",
920 "typeid"
921);
922
923my %CppKeywords_O = map {$_=>1} (
924 "bool",
925 "register",
926 "inline",
927 "operator"
928);
929
930my %CppKeywords_A = map {$_=>1} (
931 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400932 "throw",
933 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400934);
935
936foreach (keys(%CppKeywords_C),
937keys(%CppKeywords_F),
938keys(%CppKeywords_O)) {
939 $CppKeywords_A{$_}=1;
940}
941
942# Header file extensions as described by gcc
943my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
944
945my %IntrinsicMangling = (
946 "void" => "v",
947 "bool" => "b",
948 "wchar_t" => "w",
949 "char" => "c",
950 "signed char" => "a",
951 "unsigned char" => "h",
952 "short" => "s",
953 "unsigned short" => "t",
954 "int" => "i",
955 "unsigned int" => "j",
956 "long" => "l",
957 "unsigned long" => "m",
958 "long long" => "x",
959 "__int64" => "x",
960 "unsigned long long" => "y",
961 "__int128" => "n",
962 "unsigned __int128" => "o",
963 "float" => "f",
964 "double" => "d",
965 "long double" => "e",
966 "__float80" => "e",
967 "__float128" => "g",
968 "..." => "z"
969);
970
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400971my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400973my %StdcxxMangling = (
974 "3std"=>"St",
975 "3std9allocator"=>"Sa",
976 "3std12basic_string"=>"Sb",
977 "3std12basic_stringIcE"=>"Ss",
978 "3std13basic_istreamIcE"=>"Si",
979 "3std13basic_ostreamIcE"=>"So",
980 "3std14basic_iostreamIcE"=>"Sd"
981);
982
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400983my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400984my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
985
986my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400987my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400989my %ConstantSuffix = (
990 "unsigned int"=>"u",
991 "long"=>"l",
992 "unsigned long"=>"ul",
993 "long long"=>"ll",
994 "unsigned long long"=>"ull"
995);
996
997my %ConstantSuffixR =
998reverse(%ConstantSuffix);
999
1000my %OperatorMangling = (
1001 "~" => "co",
1002 "=" => "aS",
1003 "|" => "or",
1004 "^" => "eo",
1005 "&" => "an",#ad (addr)
1006 "==" => "eq",
1007 "!" => "nt",
1008 "!=" => "ne",
1009 "<" => "lt",
1010 "<=" => "le",
1011 "<<" => "ls",
1012 "<<=" => "lS",
1013 ">" => "gt",
1014 ">=" => "ge",
1015 ">>" => "rs",
1016 ">>=" => "rS",
1017 "()" => "cl",
1018 "%" => "rm",
1019 "[]" => "ix",
1020 "&&" => "aa",
1021 "||" => "oo",
1022 "*" => "ml",#de (deref)
1023 "++" => "pp",#
1024 "--" => "mm",#
1025 "new" => "nw",
1026 "delete" => "dl",
1027 "new[]" => "na",
1028 "delete[]" => "da",
1029 "+=" => "pL",
1030 "+" => "pl",#ps (pos)
1031 "-" => "mi",#ng (neg)
1032 "-=" => "mI",
1033 "*=" => "mL",
1034 "/=" => "dV",
1035 "&=" => "aN",
1036 "|=" => "oR",
1037 "%=" => "rM",
1038 "^=" => "eO",
1039 "/" => "dv",
1040 "->*" => "pm",
1041 "->" => "pt",#rf (ref)
1042 "," => "cm",
1043 "?" => "qu",
1044 "." => "dt",
1045 "sizeof"=> "sz"#st
1046);
1047
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001048my %Intrinsic_Keywords = map {$_=>1} (
1049 "true",
1050 "false",
1051 "_Bool",
1052 "_Complex",
1053 "const",
1054 "int",
1055 "long",
1056 "void",
1057 "short",
1058 "float",
1059 "volatile",
1060 "restrict",
1061 "unsigned",
1062 "signed",
1063 "char",
1064 "double",
1065 "class",
1066 "struct",
1067 "union",
1068 "enum"
1069);
1070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001071my %GlibcHeader = map {$_=>1} (
1072 "aliases.h",
1073 "argp.h",
1074 "argz.h",
1075 "assert.h",
1076 "cpio.h",
1077 "ctype.h",
1078 "dirent.h",
1079 "envz.h",
1080 "errno.h",
1081 "error.h",
1082 "execinfo.h",
1083 "fcntl.h",
1084 "fstab.h",
1085 "ftw.h",
1086 "glob.h",
1087 "grp.h",
1088 "iconv.h",
1089 "ifaddrs.h",
1090 "inttypes.h",
1091 "langinfo.h",
1092 "limits.h",
1093 "link.h",
1094 "locale.h",
1095 "malloc.h",
1096 "math.h",
1097 "mntent.h",
1098 "monetary.h",
1099 "nl_types.h",
1100 "obstack.h",
1101 "printf.h",
1102 "pwd.h",
1103 "regex.h",
1104 "sched.h",
1105 "search.h",
1106 "setjmp.h",
1107 "shadow.h",
1108 "signal.h",
1109 "spawn.h",
1110 "stdarg.h",
1111 "stdint.h",
1112 "stdio.h",
1113 "stdlib.h",
1114 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001115 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001116 "tar.h",
1117 "termios.h",
1118 "time.h",
1119 "ulimit.h",
1120 "unistd.h",
1121 "utime.h",
1122 "wchar.h",
1123 "wctype.h",
1124 "wordexp.h" );
1125
1126my %GlibcDir = map {$_=>1} (
1127 "arpa",
1128 "bits",
1129 "gnu",
1130 "netinet",
1131 "net",
1132 "nfs",
1133 "rpc",
1134 "sys",
1135 "linux" );
1136
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001137my %WinHeaders = map {$_=>1} (
1138 "dos.h",
1139 "process.h",
1140 "winsock.h",
1141 "config-win.h",
1142 "mem.h",
1143 "windows.h",
1144 "winsock2.h",
1145 "crtdbg.h",
1146 "ws2tcpip.h"
1147);
1148
1149my %ObsoleteHeaders = map {$_=>1} (
1150 "iostream.h",
1151 "fstream.h"
1152);
1153
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001154my %AlienHeaders = map {$_=>1} (
1155 # Solaris
1156 "thread.h",
1157 "sys/atomic.h",
1158 # HPUX
1159 "sys/stream.h",
1160 # Symbian
1161 "AknDoc.h",
1162 # Atari ST
1163 "ext.h",
1164 "tos.h",
1165 # MS-DOS
1166 "alloc.h",
1167 # Sparc
1168 "sys/atomic.h"
1169);
1170
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001171my %ConfHeaders = map {$_=>1} (
1172 "atomic",
1173 "conf.h",
1174 "config.h",
1175 "configure.h",
1176 "build.h",
1177 "setup.h"
1178);
1179
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001180my %LocalIncludes = map {$_=>1} (
1181 "/usr/local/include",
1182 "/usr/local" );
1183
1184my %OS_AddPath=(
1185# These paths are needed if the tool cannot detect them automatically
1186 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001187 "include"=>[
1188 "/Library",
1189 "/Developer/usr/include"
1190 ],
1191 "lib"=>[
1192 "/Library",
1193 "/Developer/usr/lib"
1194 ],
1195 "bin"=>[
1196 "/Developer/usr/bin"
1197 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001198 },
1199 "beos"=>{
1200 # Haiku has GCC 2.95.3 by default
1201 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001202 "include"=>[
1203 "/boot/common",
1204 "/boot/develop"
1205 ],
1206 "lib"=>[
1207 "/boot/common/lib",
1208 "/boot/system/lib",
1209 "/boot/apps"
1210 ],
1211 "bin"=>[
1212 "/boot/common/bin",
1213 "/boot/system/bin",
1214 "/boot/develop/abi"
1215 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001217);
1218
1219my %Slash_Type=(
1220 "default"=>"/",
1221 "windows"=>"\\"
1222);
1223
1224my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1225
1226# Global Variables
1227my %COMMON_LANGUAGE=(
1228 1 => "C",
1229 2 => "C" );
1230
1231my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001232my $MAX_CPPFILT_FILE_SIZE = 50000;
1233my $CPPFILT_SUPPORT_FILE;
1234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001235my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001237my $STDCXX_TESTING = 0;
1238my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001239my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001240
1241my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001242my $CheckUndefined = 0;
1243
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001244my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001245if($TargetComponent_Opt) {
1246 $TargetComponent = lc($TargetComponent_Opt);
1247}
1248else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001249{ # default: library
1250 # other components: header, system, ...
1251 $TargetComponent = "library";
1252}
1253
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001254my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001255
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001256my $SystemRoot;
1257
1258my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001259my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001260my %LOG_PATH;
1261my %DEBUG_PATH;
1262my %Cache;
1263my %LibInfo;
1264my $COMPILE_ERRORS = 0;
1265my %CompilerOptions;
1266my %CheckedDyLib;
1267my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1268
1269# Constants (#defines)
1270my %Constants;
1271my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001272my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001273
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001274# Extra Info
1275my %SymbolHeader;
1276my %KnownLibs;
1277
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001278# Templates
1279my %TemplateInstance;
1280my %BasicTemplate;
1281my %TemplateArg;
1282my %TemplateDecl;
1283my %TemplateMap;
1284
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001285# Types
1286my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287my %SkipTypes = (
1288 "1"=>{},
1289 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001290my %CheckedTypes;
1291my %TName_Tid;
1292my %EnumMembName_Id;
1293my %NestedNameSpaces = (
1294 "1"=>{},
1295 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001296my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001297my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001298my %ClassVTable;
1299my %ClassVTable_Content;
1300my %VTableClass;
1301my %AllocableClass;
1302my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001303my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001304my %Class_SubClasses;
1305my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001306my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001307my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001308
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001309my %CheckedTypeInfo;
1310
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001311# Typedefs
1312my %Typedef_BaseName;
1313my %Typedef_Tr;
1314my %Typedef_Eq;
1315my %StdCxxTypedef;
1316my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001317my %MissedBase;
1318my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001319my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001320
1321# Symbols
1322my %SymbolInfo;
1323my %tr_name;
1324my %mangled_name_gcc;
1325my %mangled_name;
1326my %SkipSymbols = (
1327 "1"=>{},
1328 "2"=>{} );
1329my %SkipNameSpaces = (
1330 "1"=>{},
1331 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001332my %AddNameSpaces = (
1333 "1"=>{},
1334 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001335my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001336my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001337my %SymbolsList_App;
1338my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001339my %Symbol_Library = (
1340 "1"=>{},
1341 "2"=>{} );
1342my %Library_Symbol = (
1343 "1"=>{},
1344 "2"=>{} );
1345my %DepSymbol_Library = (
1346 "1"=>{},
1347 "2"=>{} );
1348my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349 "1"=>{},
1350 "2"=>{} );
1351my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001352my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001353my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001354my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001355my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001356my %Library_Needed= (
1357 "1"=>{},
1358 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001359
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001360# Extra Info
1361my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001362my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001364# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001365my %Include_Preamble = (
1366 "1"=>[],
1367 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001368my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001369my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001370my %HeaderName_Paths;
1371my %Header_Dependency;
1372my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001373my %Include_Paths = (
1374 "1"=>[],
1375 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376my %INC_PATH_AUTODETECT = (
1377 "1"=>1,
1378 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001379my %Add_Include_Paths = (
1380 "1"=>[],
1381 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001382my %Skip_Include_Paths;
1383my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384my %Header_ErrorRedirect;
1385my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001386my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001387my %Header_ShouldNotBeUsed;
1388my %RecursiveIncludes;
1389my %Header_Include_Prefix;
1390my %SkipHeaders;
1391my %SkipHeadersList=(
1392 "1"=>{},
1393 "2"=>{} );
1394my %SkipLibs;
1395my %Include_Order;
1396my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001397my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001398my %TUnit_Funcs;
1399my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001400
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001401my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402 "1"=>0,
1403 "2"=>0 );
1404my %AutoPreambleMode = (
1405 "1"=>0,
1406 "2"=>0 );
1407my %MinGWMode = (
1408 "1"=>0,
1409 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001410my %Cpp0xMode = (
1411 "1"=>0,
1412 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413
1414# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001415my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001416my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001417my %RegisteredSONAMEs;
1418my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001419
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001420my %CheckedArch;
1421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422# System Objects
1423my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001424my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001425my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001426
1427# System Headers
1428my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001429my @DefaultCppPaths;
1430my @DefaultGccPaths;
1431my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001432my %DefaultCppHeader;
1433my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001434my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001435
1436# Merging
1437my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438my $Version;
1439my %AddedInt;
1440my %RemovedInt;
1441my %AddedInt_Virt;
1442my %RemovedInt_Virt;
1443my %VirtualReplacement;
1444my %ChangedTypedef;
1445my %CompatRules;
1446my %IncompleteRules;
1447my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001448my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001449my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001450my %ReturnedClass;
1451my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001452my %SourceAlternative;
1453my %SourceAlternative_B;
1454my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001455my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001456
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001457# Calling Conventions
1458my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001459 1=>{ "R"=>0, "P"=>0 },
1460 2=>{ "R"=>0, "P"=>0 }
1461);
1462
1463# ABI Dump
1464my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001465
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001466# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001467my %TargetLibs;
1468my %TargetHeaders;
1469
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001470# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471my $OStarget = $OSgroup;
1472my %TargetTools;
1473
1474# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001475my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001476
1477# Recursion locks
1478my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001479my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001480my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001481my @RecurInclude;
1482my @RecurConstant;
1483
1484# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001485my %SystemPaths = (
1486 "include"=>[],
1487 "lib"=>[],
1488 "bin"=>[]
1489);
1490my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my $GCC_PATH;
1492
1493# Symbols versioning
1494my %SymVer = (
1495 "1"=>{},
1496 "2"=>{} );
1497
1498# Problem descriptions
1499my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001500my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001501my %TotalAffected;
1502
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001503# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001504my $ContentID = 1;
1505my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1506my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1507my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1508my $ContentSpanEnd = "</span>\n";
1509my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1510my $ContentDivEnd = "</div>\n";
1511my $Content_Counter = 0;
1512
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001513# Modes
1514my $JoinReport = 1;
1515my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001516
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001517my %Severity_Val=(
1518 "High"=>3,
1519 "Medium"=>2,
1520 "Low"=>1,
1521 "Safe"=>-1
1522);
1523
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001524sub get_Modules()
1525{
1526 my $TOOL_DIR = get_dirname($0);
1527 if(not $TOOL_DIR)
1528 { # patch for MS Windows
1529 $TOOL_DIR = ".";
1530 }
1531 my @SEARCH_DIRS = (
1532 # tool's directory
1533 abs_path($TOOL_DIR),
1534 # relative path to modules
1535 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001536 # install path
1537 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001538 );
1539 foreach my $DIR (@SEARCH_DIRS)
1540 {
1541 if(not is_abs($DIR))
1542 { # relative path
1543 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1544 }
1545 if(-d $DIR."/modules") {
1546 return $DIR."/modules";
1547 }
1548 }
1549 exitStatus("Module_Error", "can't find modules");
1550}
1551
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001552my %LoadedModules = ();
1553
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001554sub loadModule($)
1555{
1556 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001557 if(defined $LoadedModules{$Name}) {
1558 return;
1559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001560 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1561 if(not -f $Path) {
1562 exitStatus("Module_Error", "can't access \'$Path\'");
1563 }
1564 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001565 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001566}
1567
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001568sub readModule($$)
1569{
1570 my ($Module, $Name) = @_;
1571 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1572 if(not -f $Path) {
1573 exitStatus("Module_Error", "can't access \'$Path\'");
1574 }
1575 return readFile($Path);
1576}
1577
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001578sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001580 my $Number = $_[0];
1581 if(not $Number) {
1582 $Number = 1;
1583 }
1584 else {
1585 $Number = int($Number)+1;
1586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001587 if($Number>3) {
1588 return $Number."th";
1589 }
1590 elsif($Number==1) {
1591 return "1st";
1592 }
1593 elsif($Number==2) {
1594 return "2nd";
1595 }
1596 elsif($Number==3) {
1597 return "3rd";
1598 }
1599 else {
1600 return $Number;
1601 }
1602}
1603
1604sub search_Tools($)
1605{
1606 my $Name = $_[0];
1607 return "" if(not $Name);
1608 if(my @Paths = keys(%TargetTools))
1609 {
1610 foreach my $Path (@Paths)
1611 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001612 if(-f join_P($Path, $Name)) {
1613 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001614 }
1615 if($CrossPrefix)
1616 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001617 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001618 if(-f $Candidate) {
1619 return $Candidate;
1620 }
1621 }
1622 }
1623 }
1624 else {
1625 return "";
1626 }
1627}
1628
1629sub synch_Cmd($)
1630{
1631 my $Name = $_[0];
1632 if(not $GCC_PATH)
1633 { # GCC was not found yet
1634 return "";
1635 }
1636 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001637 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001638 return $Candidate;
1639 }
1640 return "";
1641}
1642
1643sub get_CmdPath($)
1644{
1645 my $Name = $_[0];
1646 return "" if(not $Name);
1647 if(defined $Cache{"get_CmdPath"}{$Name}) {
1648 return $Cache{"get_CmdPath"}{$Name};
1649 }
1650 my %BinUtils = map {$_=>1} (
1651 "c++filt",
1652 "objdump",
1653 "readelf"
1654 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001655 if($BinUtils{$Name} and $GCC_PATH)
1656 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001657 if(my $Dir = get_dirname($GCC_PATH)) {
1658 $TargetTools{$Dir}=1;
1659 }
1660 }
1661 my $Path = search_Tools($Name);
1662 if(not $Path and $OSgroup eq "windows") {
1663 $Path = search_Tools($Name.".exe");
1664 }
1665 if(not $Path and $BinUtils{$Name})
1666 {
1667 if($CrossPrefix)
1668 { # user-defined prefix
1669 $Path = search_Cmd($CrossPrefix."-".$Name);
1670 }
1671 }
1672 if(not $Path and $BinUtils{$Name})
1673 {
1674 if(my $Candidate = synch_Cmd($Name))
1675 { # synch with GCC
1676 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001677 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001678 if(-f $Candidate) {
1679 $Path = $Candidate;
1680 }
1681 }
1682 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001683 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001684 $Path = $Candidate;
1685 }
1686 }
1687 }
1688 if(not $Path) {
1689 $Path = search_Cmd($Name);
1690 }
1691 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001692 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001693 $Path=search_Cmd($Name.".exe");
1694 }
1695 if($Path=~/\s/) {
1696 $Path = "\"".$Path."\"";
1697 }
1698 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1699}
1700
1701sub search_Cmd($)
1702{
1703 my $Name = $_[0];
1704 return "" if(not $Name);
1705 if(defined $Cache{"search_Cmd"}{$Name}) {
1706 return $Cache{"search_Cmd"}{$Name};
1707 }
1708 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1709 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1710 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001711 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001712 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001713 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001714 if(-f $CmdPath)
1715 {
1716 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001717 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001718 }
1719 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1720 }
1721 }
1722 return ($Cache{"search_Cmd"}{$Name} = "");
1723}
1724
1725sub get_CmdPath_Default($)
1726{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001727 return "" if(not $_[0]);
1728 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1729 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001730 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001731 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1732}
1733
1734sub get_CmdPath_Default_I($)
1735{ # search in PATH
1736 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001737 if($Name=~/find/)
1738 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001739 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001740 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001741 }
1742 }
1743 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001744 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001745 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001746 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001747 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001749 if($OSgroup eq "windows")
1750 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001751 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001752 return $Name;
1753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001754 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001755 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001756 {
1757 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001758 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001759 }
1760 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001761 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001762}
1763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001764sub classifyPath($)
1765{
1766 my $Path = $_[0];
1767 if($Path=~/[\*\[]/)
1768 { # wildcard
1769 $Path=~s/\*/.*/g;
1770 $Path=~s/\\/\\\\/g;
1771 return ($Path, "Pattern");
1772 }
1773 elsif($Path=~/[\/\\]/)
1774 { # directory or relative path
1775 return (path_format($Path, $OSgroup), "Path");
1776 }
1777 else {
1778 return ($Path, "Name");
1779 }
1780}
1781
1782sub readDescriptor($$)
1783{
1784 my ($LibVersion, $Content) = @_;
1785 return if(not $LibVersion);
1786 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1787 if(not $Content) {
1788 exitStatus("Error", "$DName is empty");
1789 }
1790 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001791 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001792 }
1793 $Content=~s/\/\*(.|\n)+?\*\///g;
1794 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001795
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1797 if($TargetVersion{$LibVersion}) {
1798 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1799 }
1800 if(not $Descriptor{$LibVersion}{"Version"}) {
1801 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1802 }
1803 if($Content=~/{RELPATH}/)
1804 {
1805 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1806 $Content =~ s/{RELPATH}/$RelDir/g;
1807 }
1808 else
1809 {
1810 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1811 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1812 }
1813 }
1814
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001815 my $DHeaders = parseTag(\$Content, "headers");
1816 if(not $DHeaders) {
1817 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1818 }
1819 elsif(lc($DHeaders) ne "none")
1820 { # append the descriptor headers list
1821 if($Descriptor{$LibVersion}{"Headers"})
1822 { # multiple descriptors
1823 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001825 else {
1826 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1827 }
1828 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1829 {
1830 if(not -e $Path) {
1831 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001832 }
1833 }
1834 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001835
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001836 if(not $CheckHeadersOnly_Opt)
1837 {
1838 my $DObjects = parseTag(\$Content, "libs");
1839 if(not $DObjects) {
1840 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1841 }
1842 elsif(lc($DObjects) ne "none")
1843 { # append the descriptor libraries list
1844 if($Descriptor{$LibVersion}{"Libs"})
1845 { # multiple descriptors
1846 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1847 }
1848 else {
1849 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1850 }
1851 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1852 {
1853 if(not -e $Path) {
1854 exitStatus("Access_Error", "can't access \'$Path\'");
1855 }
1856 }
1857 }
1858 }
1859 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1860 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001861 if(not -d $Path) {
1862 exitStatus("Access_Error", "can't access directory \'$Path\'");
1863 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001864 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001865 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001866 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001867 }
1868 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1869 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001870 if(not -d $Path) {
1871 exitStatus("Access_Error", "can't access directory \'$Path\'");
1872 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001873 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001874 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001875 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001876 }
1877 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1878 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 if(not -d $Path) {
1880 exitStatus("Access_Error", "can't access directory \'$Path\'");
1881 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001882 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001884 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 $TargetTools{$Path}=1;
1886 }
1887 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1888 $CrossPrefix = $Prefix;
1889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001890 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001891 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1892 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 if(not -d $Path) {
1894 exitStatus("Access_Error", "can't access directory \'$Path\'");
1895 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001896 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001898 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001899 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001900 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1902 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001903 if(not -d $Path) {
1904 exitStatus("Access_Error", "can't access directory \'$Path\'");
1905 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001906 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001907 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001908 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001909 }
1910 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001911 { # skip some auto-generated include paths
1912 if(not is_abs($Path))
1913 {
1914 if(my $P = abs_path($Path)) {
1915 $Path = $P;
1916 }
1917 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001918 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919 }
1920 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001921 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 my ($CPath, $Type) = classifyPath($Path);
1923 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001924 }
1925 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001926 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1927 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001928 if($Option!~/\A\-(Wl|l|L)/)
1929 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001930 $CompilerOptions{$LibVersion} .= " ".$Option;
1931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001932 }
1933 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1934 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1935 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001936 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001937 my ($CPath, $Type) = classifyPath($Path);
1938 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001939 }
1940 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1941 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1942 {
1943 my ($CPath, $Type) = classifyPath($Path);
1944 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1945 }
1946 if(my $DDefines = parseTag(\$Content, "defines"))
1947 {
1948 if($Descriptor{$LibVersion}{"Defines"})
1949 { # multiple descriptors
1950 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1951 }
1952 else {
1953 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1954 }
1955 }
1956 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1957 {
1958 if($Order=~/\A(.+):(.+)\Z/) {
1959 $Include_Order{$LibVersion}{$1} = $2;
1960 }
1961 }
1962 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1963 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001964 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001965 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1966 }
1967 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1968 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001969 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001970 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1971 }
1972 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1973 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1974 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001975 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1976 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001978 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1979 $SkipConstants{$LibVersion}{$Constant} = 1;
1980 }
1981 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1982 {
1983 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001984 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001985 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1986 }
1987 else {
1988 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1989 }
1990 }
1991}
1992
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001993sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001994{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001995 my $CodeRef = shift(@_);
1996 my $Tag = shift(@_);
1997 if(not $Tag or not $CodeRef) {
1998 return undef;
1999 }
2000 my $Sp = 0;
2001 if(@_) {
2002 $Sp = shift(@_);
2003 }
2004 my $Start = index(${$CodeRef}, "<$Tag>");
2005 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002006 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002007 my $End = index(${$CodeRef}, "</$Tag>");
2008 if($End!=-1)
2009 {
2010 my $TS = length($Tag)+3;
2011 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2012 substr($Content, 0, $TS-1, ""); # cut start tag
2013 substr($Content, -$TS, $TS, ""); # cut end tag
2014 if(not $Sp)
2015 {
2016 $Content=~s/\A\s+//g;
2017 $Content=~s/\s+\Z//g;
2018 }
2019 if(substr($Content, 0, 1) ne "<") {
2020 $Content = xmlSpecChars_R($Content);
2021 }
2022 return $Content;
2023 }
2024 }
2025 return undef;
2026}
2027
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002028sub getInfo($)
2029{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002030 my $DumpPath = $_[0];
2031 return if(not $DumpPath or not -f $DumpPath);
2032
2033 readTUDump($DumpPath);
2034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 # processing info
2036 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002037
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002038 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002039 setAnonTypedef_All();
2040 }
2041
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002042 getTypeInfo_All();
2043 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002044 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002045 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002046 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002047
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002048 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002049 %LibInfo = ();
2050 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002051 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002052 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002053 %TemplateDecl = ();
2054 %StdCxxTypedef = ();
2055 %MissedTypedef = ();
2056 %Typedef_Tr = ();
2057 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002058 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002059
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002060 # clean cache
2061 delete($Cache{"getTypeAttr"});
2062 delete($Cache{"getTypeDeclId"});
2063
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002064 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002065 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002066 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002067 }
2068 else
2069 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002070 if($BinaryOnly and not $ExtendedCheck)
2071 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002072 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002073 }
2074 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002075 remove_Unused($Version, "Extended");
2076 }
2077 }
2078
2079 if($CheckInfo)
2080 {
2081 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2082 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2083 }
2084
2085 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2086 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002087 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002088 }
2089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002090 if($Debug) {
2091 # debugMangling($Version);
2092 }
2093}
2094
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002095sub readTUDump($)
2096{
2097 my $DumpPath = $_[0];
2098
2099 open(TU_DUMP, $DumpPath);
2100 local $/ = undef;
2101 my $Content = <TU_DUMP>;
2102 close(TU_DUMP);
2103
2104 unlink($DumpPath);
2105
2106 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002107 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002108
2109 # clean memory
2110 undef $Content;
2111
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002112 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113
2114 foreach (0 .. $#Lines)
2115 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002116 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002117 { # get a number and attributes of a node
2118 next if(not $NodeType{$2});
2119 $LibInfo{$Version}{"info_type"}{$1}=$2;
2120 $LibInfo{$Version}{"info"}{$1}=$3;
2121 }
2122
2123 # clean memory
2124 delete($Lines[$_]);
2125 }
2126
2127 # clean memory
2128 undef @Lines;
2129}
2130
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002131sub simplifyConstants()
2132{
2133 foreach my $Constant (keys(%{$Constants{$Version}}))
2134 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002135 if(defined $Constants{$Version}{$Constant}{"Header"})
2136 {
2137 my $Value = $Constants{$Version}{$Constant}{"Value"};
2138 if(defined $EnumConstants{$Version}{$Value}) {
2139 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2140 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002141 }
2142 }
2143}
2144
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002145sub simplifyNames()
2146{
2147 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2148 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002149 if($Typedef_Eq{$Version}{$Base}) {
2150 next;
2151 }
2152 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2153 if($#Translations==0)
2154 {
2155 if(length($Translations[0])<=length($Base)) {
2156 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2157 }
2158 }
2159 else
2160 { # select most appropriate
2161 foreach my $Tr (@Translations)
2162 {
2163 if($Base=~/\A\Q$Tr\E/)
2164 {
2165 $Typedef_Eq{$Version}{$Base} = $Tr;
2166 last;
2167 }
2168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002169 }
2170 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002171 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002172 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002173 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002174 if(not $TypeName) {
2175 next;
2176 }
2177 next if(index($TypeName,"<")==-1);# template instances only
2178 if($TypeName=~/>(::\w+)+\Z/)
2179 { # skip unused types
2180 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002181 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002182 foreach my $Base (sort {length($b)<=>length($a)}
2183 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002184 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002185 next if(not $Base);
2186 next if(index($TypeName,$Base)==-1);
2187 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002188 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002189 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002190 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2191 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2192 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002193 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002194 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2195 {
2196 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2197 {
2198 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2199 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002200 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002201 }
2202 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002205 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002206 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002207 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2208 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002209 }
2210}
2211
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002212sub setAnonTypedef_All()
2213{
2214 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2215 {
2216 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2217 {
2218 if(isAnon(getNameByInfo($InfoId))) {
2219 $TypedefToAnon{getTypeId($InfoId)} = 1;
2220 }
2221 }
2222 }
2223}
2224
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002225sub setTemplateParams_All()
2226{
2227 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2228 {
2229 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2230 setTemplateParams($_);
2231 }
2232 }
2233}
2234
2235sub setTemplateParams($)
2236{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002237 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002238 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002239 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002240 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002241 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002242 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002243 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002244 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002245 setTemplateInstParams($_[0], $TmplInst_Id);
2246 }
2247 }
2248
2249 $BasicTemplate{$Version}{$Tid} = $_[0];
2250
2251 if(my $Prms = getTreeAttr_Prms($_[0]))
2252 {
2253 if(my $Valu = getTreeAttr_Valu($Prms))
2254 {
2255 my $Vector = getTreeVec($Valu);
2256 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2257 {
2258 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2259 {
2260 if(my $Name = getNameByInfo($Val))
2261 {
2262 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2263 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2264 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2265 }
2266 else {
2267 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2268 }
2269 }
2270 }
2271 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002273 }
2274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002275 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002276 {
2277 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2278 {
2279 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002280 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002281 }
2282 }
2283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002284}
2285
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002286sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002287{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002288 my ($Tmpl, $Inst) = @_;
2289
2290 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002291 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002292 my ($Params_InfoId, $ElemId) = ();
2293 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2294 $Params_InfoId = $1;
2295 }
2296 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2297 $ElemId = $1;
2298 }
2299 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002300 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002301 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2302 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2303 {
2304 my ($PPos, $PTypeId) = ($1, $2);
2305 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2306 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002307 if($PType eq "template_type_parm") {
2308 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002309 }
2310 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002311 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2312 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002313 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002314 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002316 else
2317 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002318 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002319 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002321 }
2322 }
2323 }
2324}
2325
2326sub getTypeDeclId($)
2327{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002328 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002330 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2331 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2332 }
2333 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2334 {
2335 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2336 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2337 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002339 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002340 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341}
2342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002343sub getTypeInfo_All()
2344{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002345 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002346 { # support for GCC < 4.5
2347 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2348 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2349 # FIXME: check GCC versions
2350 addMissedTypes_Pre();
2351 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002353 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002354 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002355 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2356 if($IType=~/_type\Z/ and $IType ne "function_type"
2357 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002358 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002359 }
2360 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002361
2362 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002363 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002364 "Name" => "...",
2365 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002366 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002368 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002369
2370 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002371 { # support for GCC < 4.5
2372 addMissedTypes_Post();
2373 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002374
2375 if($ADD_TMPL_INSTANCES)
2376 {
2377 # templates
2378 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2379 {
2380 if(defined $TemplateMap{$Version}{$Tid}
2381 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2382 {
2383 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2384 {
2385 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2386 {
2387 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2388 {
2389 if(my %MAttr = getTypeAttr($MembTypeId))
2390 {
2391 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2392 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2393 }
2394 }
2395 }
2396 }
2397 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2398 {
2399 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2400 {
2401 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2402
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002403 if($NBid ne $Bid
2404 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002405 {
2406 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2407 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2408 }
2409 }
2410 }
2411 }
2412 }
2413 }
2414}
2415
2416sub createType($$)
2417{
2418 my ($Attr, $LibVersion) = @_;
2419 my $NewId = ++$MAX_ID;
2420
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002421 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002422 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002423 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002424
2425 return "$NewId";
2426}
2427
2428sub instType($$$)
2429{ # create template instances
2430 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002431
2432 if(not $TypeInfo{$LibVersion}{$Tid}) {
2433 return undef;
2434 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002435 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2436
2437 foreach my $Key (sort keys(%{$Map}))
2438 {
2439 if(my $Val = $Map->{$Key})
2440 {
2441 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2442
2443 if(defined $Attr->{"NameSpace"}) {
2444 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2445 }
2446 foreach (keys(%{$Attr->{"TParam"}})) {
2447 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2448 }
2449 }
2450 else
2451 { # remove absent
2452 # _Traits, etc.
2453 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002454 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002455 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2456 }
2457 foreach (keys(%{$Attr->{"TParam"}}))
2458 {
2459 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2460 delete($Attr->{"TParam"}{$_});
2461 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002462 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002463 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2464 }
2465 }
2466 }
2467 }
2468
2469 my $Tmpl = 0;
2470
2471 if(defined $Attr->{"TParam"})
2472 {
2473 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2474 {
2475 my $PName = $Attr->{"TParam"}{$_}{"name"};
2476
2477 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2478 {
2479 my %Base = get_BaseType($PTid, $LibVersion);
2480
2481 if($Base{"Type"} eq "TemplateParam"
2482 or defined $Base{"Template"})
2483 {
2484 $Tmpl = 1;
2485 last
2486 }
2487 }
2488 }
2489 }
2490
2491 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2492 return "$Id";
2493 }
2494 else
2495 {
2496 if(not $Tmpl) {
2497 delete($Attr->{"Template"});
2498 }
2499
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002500 my $New = createType($Attr, $LibVersion);
2501
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002502 my %EMap = ();
2503 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2504 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2505 }
2506 foreach (keys(%{$Map})) {
2507 $EMap{$_} = $Map->{$_};
2508 }
2509
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002510 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2511 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002512 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002513 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002514 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002515 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002516 {
2517 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2518
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002519 if($NBid ne $Bid
2520 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002521 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002522 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2523 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002524 }
2525 }
2526 }
2527
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002528 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002530 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2531 {
2532 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2533 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2534 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 }
2536 }
2537
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002538 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002539 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002540 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2541 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002542 }
2543 }
2544
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002545 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2546 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002547 }
2548
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002549 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002551}
2552
2553sub addMissedTypes_Pre()
2554{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002555 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002556 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2557 { # detecting missed typedefs
2558 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2559 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002560 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002561 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002562 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002563 if($TypeType eq "Unknown")
2564 { # template_type_parm
2565 next;
2566 }
2567 my $TypeDeclId = getTypeDeclId($TypeId);
2568 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2569 my $TypedefName = getNameByInfo($MissedTDid);
2570 next if(not $TypedefName);
2571 next if($TypedefName eq "__float80");
2572 next if(isAnon($TypedefName));
2573 if(not $TypeDeclId
2574 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002575 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002576 }
2577 }
2578 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002579 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002580 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002582 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002584 next;
2585 }
2586 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002587 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002588 if(not $TypedefName) {
2589 next;
2590 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002591 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 my %MissedInfo = ( # typedef info
2593 "Name" => $TypedefName,
2594 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002595 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002597 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002598 my ($H, $L) = getLocation($MissedTDid);
2599 $MissedInfo{"Header"} = $H;
2600 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002601 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002602 { # other types
2603 next;
2604 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002605 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002607 next;
2608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002609 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002611 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002613 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 next;
2616 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002617 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 next;
2619 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002620 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002621 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622 next;
2623 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002624 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 next;
2627 }
2628 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002629
2630 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002632 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002633 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002634 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002635 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002636 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002637
2638 # add missed & remove other
2639 $TypeInfo{$Version} = \%AddTypes;
2640 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641}
2642
2643sub addMissedTypes_Post()
2644{
2645 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2646 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002647 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2648 {
2649 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2650 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2651 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2652 }
2653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654 }
2655}
2656
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002657sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002658{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002659 my $TypeId = $_[0];
2660 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2661 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002662 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002663 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002665}
2666
2667sub getArraySize($$)
2668{
2669 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002670 if(my $Size = getSize($TypeId))
2671 {
2672 my $Elems = $Size/$BYTE_SIZE;
2673 while($BaseName=~s/\s*\[(\d+)\]//) {
2674 $Elems/=$1;
2675 }
2676 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2677 {
2678 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2679 $Elems/=$BasicSize;
2680 }
2681 }
2682 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002684 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002685}
2686
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002687sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002688{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002689 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002690 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002691 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2692 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002693 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002694 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2695 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2696 if(not $NodeType)
2697 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698 return ();
2699 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002700 if($NodeType eq "tree_vec")
2701 {
2702 if($Pos!=$#Positions)
2703 { # select last vector of parameters ( ns<P1>::type<P2> )
2704 next;
2705 }
2706 }
2707 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2708 foreach my $P (@Params)
2709 {
2710 if($P eq "") {
2711 return ();
2712 }
2713 elsif($P ne "\@skip\@") {
2714 @TmplParams = (@TmplParams, $P);
2715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 }
2717 }
2718 return @TmplParams;
2719}
2720
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002721sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002723 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002724 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002725 if(defined $TypeInfo{$Version}{$TypeId}
2726 and $TypeInfo{$Version}{$TypeId}{"Name"})
2727 { # already created
2728 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002729 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002730 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2731 { # incomplete type
2732 return ();
2733 }
2734 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2735
2736 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738
2739 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2740 {
2741 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2742 {
2743 if($Info=~/qual[ ]*:/)
2744 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002745 my $NewId = ++$MAX_ID;
2746
2747 $MissedBase{$Version}{$TypeId} = "$NewId";
2748 $MissedBase_R{$Version}{$NewId} = $TypeId;
2749 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2750 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002751 }
2752 }
2753 $TypeAttr{"Type"} = "Typedef";
2754 }
2755 else {
2756 $TypeAttr{"Type"} = getTypeType($TypeId);
2757 }
2758
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002759 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2760 {
2761 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2762 { # local code
2763 return ();
2764 }
2765 }
2766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 if($TypeAttr{"Type"} eq "Unknown") {
2768 return ();
2769 }
2770 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002772 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002773 if(my $TName = $TypeAttr{"Name"})
2774 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002776 $TName_Tid{$Version}{$TName} = $TypeId;
2777 return %TypeAttr;
2778 }
2779 else {
2780 return ();
2781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002782 }
2783 elsif($TypeAttr{"Type"} eq "Array")
2784 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002785 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2786 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002787 return ();
2788 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002789 if(my $Algn = getAlgn($TypeId)) {
2790 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002792 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002793 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002794 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002795 if(not $BTAttr{"Name"}) {
2796 return ();
2797 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002798 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002800 if(my $Size = getSize($TypeId)) {
2801 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2802 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002803 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002804 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2805 }
2806 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002807 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002809 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002810 else
2811 {
2812 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002813 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002814 $TypeAttr{"Name"} = $1."[]".$2;
2815 }
2816 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002817 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002819 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002820 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 if($BTAttr{"Header"}) {
2822 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002823 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002824 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002825 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2826 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002828 return ();
2829 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002830 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002831 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002832 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002833 if($TypeAttr{"Name"})
2834 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002835 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002836
2837 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2838 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002839 { # NOTE: register only one int: with built-in decl
2840 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2841 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2842 }
2843 }
2844 return %TypeAttr;
2845 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002846 else {
2847 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002849 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002850 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2851 {
2852 %TypeAttr = getTrivialTypeAttr($TypeId);
2853 if($TypeAttr{"Name"})
2854 {
2855 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2856 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2857 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2858 }
2859 return %TypeAttr;
2860 }
2861 else {
2862 return ();
2863 }
2864 }
2865 elsif($TypeAttr{"Type"} eq "SizeOf")
2866 {
2867 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2868 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2869 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2870 if($TypeAttr{"Name"})
2871 {
2872 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2873 return %TypeAttr;
2874 }
2875 else {
2876 return ();
2877 }
2878 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002879 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002880 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002881 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2882 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002883 return ();
2884 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002885 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002887 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002888 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002889 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002890 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002891 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 }
2894 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002895 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002896 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002897 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002898 return ();
2899 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002900 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002901 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002902 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002903 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002904 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002905 }
2906 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002907 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002908 {
2909 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002910 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002911 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002912 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002913 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2914 }
2915 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002916 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002917 }
2918 }
2919 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002920 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002921 }
2922 if($TypeAttr{"Type"} eq "Typedef")
2923 {
2924 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002925
2926 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2927 return ();
2928 }
2929
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002930 if(isAnon($TypeAttr{"Name"}))
2931 { # anon typedef to anon type: ._N
2932 return ();
2933 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002934
2935 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2936 { # artificial typedef of "struct X" to "X"
2937 $TypeAttr{"Artificial"} = 1;
2938 }
2939
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002940 if(my $NS = getNameSpace($TypeDeclId))
2941 {
2942 my $TypeName = $TypeAttr{"Name"};
2943 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2944 { # "some_type" is the typedef to "struct some_type" in C++
2945 if($3) {
2946 $TypeAttr{"Name"} = $3."::".$TypeName;
2947 }
2948 }
2949 else
2950 {
2951 $TypeAttr{"NameSpace"} = $NS;
2952 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002953
2954 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2955 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2956 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002957 if($BTAttr{"NameSpace"}
2958 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002959 { # types like "std::fpos<__mbstate_t>" are
2960 # not covered by typedefs in the TU dump
2961 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002962 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2963 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002964 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002966 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002967 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002969 }
2970 }
2971 }
2972 }
2973 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002974 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002975 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002976 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002977 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2978 { # typedef int*const TYPEDEF; // first
2979 # int foo(TYPEDEF p); // const is optimized out
2980 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2981 if($BTAttr{"Name"}=~/</)
2982 {
2983 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2984 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002986 }
2987 }
2988 }
2989 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2990 }
2991 if(not $TypeAttr{"Size"})
2992 {
2993 if($TypeAttr{"Type"} eq "Pointer") {
2994 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2995 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002996 elsif($BTAttr{"Size"}) {
2997 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002998 }
2999 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003000 if(my $Algn = getAlgn($TypeId)) {
3001 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3002 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003003 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003004 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3005 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003006 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003007 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003008 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003009 { # typedef to "class Class"
3010 # should not be registered in TName_Tid
3011 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3012 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003014 }
3015 return %TypeAttr;
3016 }
3017}
3018
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003019sub getTreeVec($)
3020{
3021 my %Vector = ();
3022 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3023 {
3024 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3025 { # string length is N-1 because of the null terminator
3026 $Vector{$1} = $2;
3027 }
3028 }
3029 return \%Vector;
3030}
3031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003032sub get_TemplateParam($$)
3033{
3034 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003035 return () if(not $Type_Id);
3036 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3037 return () if(not $NodeType);
3038 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003039 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003040 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003041 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 my $Num = getNodeIntCst($Type_Id);
3043 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003044 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003045 }
3046 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003047 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003048 }
3049 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003050 elsif($NodeType eq "string_cst") {
3051 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003053 elsif($NodeType eq "tree_vec")
3054 {
3055 my $Vector = getTreeVec($Type_Id);
3056 my @Params = ();
3057 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3058 {
3059 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3060 push(@Params, $P2);
3061 }
3062 }
3063 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003064 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003065 elsif($NodeType eq "parm_decl")
3066 {
3067 (getNameByInfo($Type_Id));
3068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 else
3070 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003071 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003072 my $PName = $ParamAttr{"Name"};
3073 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003074 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003075 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003076 if($PName=~/\>/)
3077 {
3078 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003079 $PName = $Cover;
3080 }
3081 }
3082 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003083 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003084 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3085 # template<typename _Key, typename _Compare = std::less<_Key>
3086 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3087 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3088 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3089 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003090 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003091 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003092 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 }
3094}
3095
3096sub cover_stdcxx_typedef($)
3097{
3098 my $TypeName = $_[0];
3099 if(my @Covers = sort {length($a)<=>length($b)}
3100 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3101 { # take the shortest typedef
3102 # FIXME: there may be more than
3103 # one typedefs to the same type
3104 return $Covers[0];
3105 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003106 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003107 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3108 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3109 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003110 if(my $Cover = $Covers[0])
3111 {
3112 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3113 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003115 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003116 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003117}
3118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119sub getNodeIntCst($)
3120{
3121 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003122 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 if($EnumMembName_Id{$Version}{$CstId}) {
3124 return $EnumMembName_Id{$Version}{$CstId};
3125 }
3126 elsif((my $Value = getTreeValue($CstId)) ne "")
3127 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003128 if($Value eq "0")
3129 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003130 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003131 return "false";
3132 }
3133 else {
3134 return "0";
3135 }
3136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003137 elsif($Value eq "1")
3138 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003139 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003140 return "true";
3141 }
3142 else {
3143 return "1";
3144 }
3145 }
3146 else {
3147 return $Value;
3148 }
3149 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003150 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003151}
3152
3153sub getNodeStrCst($)
3154{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003155 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3156 {
3157 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003158 {
3159 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3160 { # string length is N-1 because of the null terminator
3161 return substr($1, 0, $2-1);
3162 }
3163 else
3164 { # identifier_node
3165 return substr($1, 0, $2);
3166 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003169 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003170}
3171
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003172sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003174 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003175 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3176 if($Type eq "FieldPtr") {
3177 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3178 }
3179 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3180 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003181 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003182 if($Type eq "MethodPtr")
3183 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003184 if(my $Size = getSize($TypeId))
3185 {
3186 $Size/=$BYTE_SIZE;
3187 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003189 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003190 if(my $Algn = getAlgn($TypeId)) {
3191 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003193 # Return
3194 if($Type eq "FieldPtr")
3195 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003196 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003197 if($ReturnAttr{"Name"}) {
3198 $MemPtrName .= $ReturnAttr{"Name"};
3199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003200 $TypeAttr{"Return"} = $PtrId;
3201 }
3202 else
3203 {
3204 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3205 {
3206 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003207 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3208 if(not $ReturnAttr{"Name"})
3209 { # templates
3210 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003211 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003212 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003213 $TypeAttr{"Return"} = $ReturnTypeId;
3214 }
3215 }
3216 # Class
3217 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3218 {
3219 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003220 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003221 if($Class{"Name"}) {
3222 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3223 }
3224 else {
3225 $MemPtrName .= " (*)";
3226 }
3227 }
3228 else {
3229 $MemPtrName .= " (*)";
3230 }
3231 # Parameters
3232 if($Type eq "FuncPtr"
3233 or $Type eq "MethodPtr")
3234 {
3235 my @ParamTypeName = ();
3236 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3237 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003238 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003239 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003240 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003242 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3243 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003244 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003245 my $PTypeId = $1;
3246 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003247 if(not $ParamAttr{"Name"})
3248 { # templates (template_type_parm), etc.
3249 return ();
3250 }
3251 if($ParamAttr{"Name"} eq "void") {
3252 last;
3253 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003254 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003255 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003256 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003257 push(@ParamTypeName, $ParamAttr{"Name"});
3258 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003259 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3260 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003261 }
3262 else {
3263 last;
3264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003265 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003266 else {
3267 last;
3268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003269 }
3270 }
3271 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3272 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003273 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 return %TypeAttr;
3275}
3276
3277sub getTreeTypeName($)
3278{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003279 my $TypeId = $_[0];
3280 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003281 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003282 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003283 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003284 if(my $Name = getNameByInfo($TypeId))
3285 { # bit_size_type
3286 return $Name;
3287 }
3288 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003289 return "unsigned int";
3290 }
3291 else {
3292 return "int";
3293 }
3294 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003295 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003296 return getNameByInfo($1);
3297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003298 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003299 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003300}
3301
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003302sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003303{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003304 my $Ptd = pointTo($_[0]);
3305 return 0 if(not $Ptd);
3306 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003307 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003308 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3309 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003310 }
3311 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003312 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3313 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003314 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003315 if($InfoT1 eq "pointer_type"
3316 and $InfoT2 eq "function_type") {
3317 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318 }
3319 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003320 return 0;
3321}
3322
3323sub isMethodPtr($)
3324{
3325 my $Ptd = pointTo($_[0]);
3326 return 0 if(not $Ptd);
3327 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3328 {
3329 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3330 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3331 and $Info=~/ ptrmem /) {
3332 return 1;
3333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003334 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003335 return 0;
3336}
3337
3338sub isFieldPtr($)
3339{
3340 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3341 {
3342 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3343 and $Info=~/ ptrmem /) {
3344 return 1;
3345 }
3346 }
3347 return 0;
3348}
3349
3350sub pointTo($)
3351{
3352 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3353 {
3354 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3355 return $1;
3356 }
3357 }
3358 return "";
3359}
3360
3361sub getTypeTypeByTypeId($)
3362{
3363 my $TypeId = $_[0];
3364 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3365 {
3366 my $NType = $NodeType{$TType};
3367 if($NType eq "Intrinsic") {
3368 return $NType;
3369 }
3370 elsif(isFuncPtr($TypeId)) {
3371 return "FuncPtr";
3372 }
3373 elsif(isMethodPtr($TypeId)) {
3374 return "MethodPtr";
3375 }
3376 elsif(isFieldPtr($TypeId)) {
3377 return "FieldPtr";
3378 }
3379 elsif($NType ne "Other") {
3380 return $NType;
3381 }
3382 }
3383 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003384}
3385
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003386my %UnQual = (
3387 "r"=>"restrict",
3388 "v"=>"volatile",
3389 "c"=>"const",
3390 "cv"=>"const volatile"
3391);
3392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003393sub getQual($)
3394{
3395 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003396 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3397 {
3398 my ($Qual, $To) = ();
3399 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3400 $Qual = $UnQual{$1};
3401 }
3402 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3403 $To = $1;
3404 }
3405 if($Qual and $To) {
3406 return ($Qual, $To);
3407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003408 }
3409 return ();
3410}
3411
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003412sub getQualType($)
3413{
3414 if($_[0] eq "const volatile") {
3415 return "ConstVolatile";
3416 }
3417 return ucfirst($_[0]);
3418}
3419
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003420sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003421{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003422 my $TypeId = $_[0];
3423 my $TypeDeclId = getTypeDeclId($TypeId);
3424 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003425 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003426 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3427 return "Typedef";
3428 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003429 }
3430 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3431 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003432 if(($Qual or $To) and $TypeDeclId
3433 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003434 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003435 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003437 elsif(not $MissedBase_R{$Version}{$TypeId}
3438 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439 return "Typedef";
3440 }
3441 elsif($Qual)
3442 { # qualified types
3443 return getQualType($Qual);
3444 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003445
3446 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3447 { # typedef struct { ... } name
3448 $TypeTypedef{$Version}{$TypeId} = $1;
3449 }
3450
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003451 my $TypeType = getTypeTypeByTypeId($TypeId);
3452 if($TypeType eq "Struct")
3453 {
3454 if($TypeDeclId
3455 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3456 return "Template";
3457 }
3458 }
3459 return $TypeType;
3460}
3461
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003462sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003463{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003464 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003465 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003466 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3467 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3468 return 0;
3469 }
3470 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3471 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003472 if(my $TDid = getTypeDeclId($_[0]))
3473 {
3474 if(getTypeId($TDid) eq $_[0]
3475 and getNameByInfo($TDid))
3476 {
3477 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3478 return $1;
3479 }
3480 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003482 }
3483 }
3484 return 0;
3485}
3486
3487sub selectBaseType($)
3488{
3489 my $TypeId = $_[0];
3490 if(defined $MissedTypedef{$Version}{$TypeId})
3491 { # add missed typedefs
3492 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3493 return ($TypeId, "");
3494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003495 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003496 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3497 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003498
3499 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3500 my $MB = $MissedBase{$Version}{$TypeId};
3501
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003502 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003503 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003504 and (getTypeId($1) ne $TypeId)
3505 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003506 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003507 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003508 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 elsif($MB)
3510 { # add base
3511 return ($MB, "");
3512 }
3513 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003514 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003517 elsif($Qual or $To)
3518 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003519 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003520 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003521 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003524 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003527 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003529 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003530 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003532 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003533 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003535 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003536 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003538 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003539
3540 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541}
3542
3543sub getSymbolInfo_All()
3544{
3545 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3546 { # reverse order
3547 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003548 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 }
3550 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003551
3552 if($ADD_TMPL_INSTANCES)
3553 {
3554 # templates
3555 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3556 {
3557 my %Map = ();
3558
3559 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3560 {
3561 if(defined $TemplateMap{$Version}{$ClassId})
3562 {
3563 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3564 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3565 }
3566 }
3567 }
3568
3569 if(defined $TemplateMap{$Version}{$Sid})
3570 {
3571 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3572 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3573 }
3574 }
3575
3576 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3577 {
3578 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3579 {
3580 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3581 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3582 }
3583 }
3584 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3585 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3586 }
3587 }
3588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003589}
3590
3591sub getVarInfo_All()
3592{
3593 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3594 { # reverse order
3595 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003596 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003597 }
3598 }
3599}
3600
3601sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003602 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003603}
3604
3605sub getVarInfo($)
3606{
3607 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003608 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003609 {
3610 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3611 if($NSInfoType and $NSInfoType eq "function_decl") {
3612 return;
3613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003614 }
3615 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3616 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3617 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3618 delete($SymbolInfo{$Version}{$InfoId});
3619 return;
3620 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003621 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003622 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003623 delete($SymbolInfo{$Version}{$InfoId});
3624 return;
3625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003626 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3627 delete($SymbolInfo{$Version}{$InfoId});
3628 return;
3629 }
3630 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003631 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3632 {
3633 if($OSgroup eq "windows")
3634 { # cut the offset
3635 $MnglName=~s/\@\d+\Z//g;
3636 }
3637 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003639 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003640 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003641 { # validate mangled name
3642 delete($SymbolInfo{$Version}{$InfoId});
3643 return;
3644 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003645 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003646 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003647 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003648 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003649 }
3650 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3651 { # non-public global data
3652 delete($SymbolInfo{$Version}{$InfoId});
3653 return;
3654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003655 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003656 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003657 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003658 if(not defined $TypeInfo{$Version}{$Rid}
3659 or not $TypeInfo{$Version}{$Rid}{"Name"})
3660 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003661 delete($SymbolInfo{$Version}{$InfoId});
3662 return;
3663 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3665 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003666 if(defined $Val) {
3667 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003669 }
3670 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003671 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3672 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003673 if(not defined $TypeInfo{$Version}{$ClassId}
3674 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3675 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 delete($SymbolInfo{$Version}{$InfoId});
3677 return;
3678 }
3679 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003680 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3681 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003683 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003684 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003685 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003686 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003687 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003688 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003689 if(not $CheckHeadersOnly)
3690 {
3691 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3692 {
3693 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3694 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3695 {
3696 if(link_symbol($ShortName, $Version, "-Deps"))
3697 { # "const" global data is mangled as _ZL... in the TU dump
3698 # but not mangled when compiling a C shared library
3699 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3700 }
3701 }
3702 }
3703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003704 if($COMMON_LANGUAGE{$Version} eq "C++")
3705 {
3706 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3707 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003708 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3710 }
3711 }
3712 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3713 { # try to mangle symbol (link with libraries)
3714 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3715 }
3716 if($OStarget eq "windows")
3717 {
3718 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3719 { # link MS C++ symbols from library with GCC symbols from headers
3720 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3721 }
3722 }
3723 }
3724 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3725 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3726 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003727 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3728 {
3729 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3730 { # non-target symbols
3731 delete($SymbolInfo{$Version}{$InfoId});
3732 return;
3733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003735 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3736 {
3737 if(defined $MissedTypedef{$Version}{$Rid})
3738 {
3739 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3740 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3741 }
3742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003743 }
3744 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003745 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003746 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3747 }
3748 if($ShortName=~/\A(_Z|\?)/) {
3749 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3750 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003751
3752 if($ExtraDump) {
3753 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003755}
3756
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003757sub isConstType($$)
3758{
3759 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003760 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003761 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003762 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003763 }
3764 return ($Base{"Type"} eq "Const");
3765}
3766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003767sub getTrivialName($$)
3768{
3769 my ($TypeInfoId, $TypeId) = @_;
3770 my %TypeAttr = ();
3771 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3772 if(not $TypeAttr{"Name"}) {
3773 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3774 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003775 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003776 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003777 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003778 if(isAnon($TypeAttr{"Name"}))
3779 {
3780 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003781 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003782 { # searching for a first not anon scope
3783 if($NSId eq $NameSpaceId) {
3784 last;
3785 }
3786 else
3787 {
3788 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3789 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003790 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003791 last;
3792 }
3793 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003794 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003795 }
3796 }
3797 else
3798 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003799 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003800 {
3801 if($NameSpaceId ne $TypeId) {
3802 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003804 }
3805 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003806 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003807 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3808 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003809 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003810 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003811 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003812 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003813 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003814 if($TypeAttr{"NameSpace"}) {
3815 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003818 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3819 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003820 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003821 if(my @TParams = getTParams($TypeId, "Type")) {
3822 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3823 }
3824 else {
3825 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003827 }
3828 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3829}
3830
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003831sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003832{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003833 my $TypeId = $_[0];
3834 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003835
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003836 my %TypeAttr = ();
3837
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003838 if($TemplateDecl{$Version}{$TypeId})
3839 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003840 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003841 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003842
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003843 setTypeAccess($TypeId, \%TypeAttr);
3844 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3845 if(isBuiltIn($TypeAttr{"Header"}))
3846 {
3847 delete($TypeAttr{"Header"});
3848 delete($TypeAttr{"Line"});
3849 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003850
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003851 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003852 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3853 if(not $TypeAttr{"Name"}) {
3854 return ();
3855 }
3856 if(not $TypeAttr{"NameSpace"}) {
3857 delete($TypeAttr{"NameSpace"});
3858 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003859
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003860 if($TypeAttr{"Type"} eq "Intrinsic")
3861 {
3862 if(defined $TypeAttr{"Header"})
3863 {
3864 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3865 { # support for SUSE 11.2
3866 # integer_type has srcp dump{1-2}.i
3867 delete($TypeAttr{"Header"});
3868 }
3869 }
3870 }
3871
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003872 my $Tmpl = undef;
3873
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003874 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003875 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003876 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3877
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003878 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003879 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003880 foreach my $Pos (0 .. $#TParams)
3881 {
3882 my $Val = $TParams[$Pos];
3883 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3884
3885 if(not defined $TypeAttr{"Template"})
3886 {
3887 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3888
3889 if($Base{"Type"} eq "TemplateParam"
3890 or defined $Base{"Template"}) {
3891 $TypeAttr{"Template"} = 1;
3892 }
3893 }
3894
3895 if($Tmpl)
3896 {
3897 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3898 {
3899 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3900
3901 if($Val eq $Arg) {
3902 $TypeAttr{"Template"} = 1;
3903 }
3904 }
3905 }
3906 }
3907
3908 if($Tmpl)
3909 {
3910 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3911 {
3912 if($Pos>$#TParams)
3913 {
3914 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3915 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3916 }
3917 }
3918 }
3919 }
3920
3921 if($ADD_TMPL_INSTANCES)
3922 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003923 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003924 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003925 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003926 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003927 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003928 {
3929 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3930 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3931 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003932 }
3933 if(not getTreeAttr_Binf($TypeId))
3934 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003935 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3936 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3937 }
3938 }
3939 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003940 }
3941 }
3942 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003943
3944 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3945
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003946 if(my $Size = getSize($TypeId))
3947 {
3948 $Size = $Size/$BYTE_SIZE;
3949 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003950 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003951 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003952 {
3953 if($ExtraDump)
3954 {
3955 if(not defined $TypeAttr{"Memb"}
3956 and not $Tmpl)
3957 { # declaration only
3958 $TypeAttr{"Forward"} = 1;
3959 }
3960 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003961 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003963 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003964 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003965 {
3966 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003967 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003968 }
3969 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003970 or $TypeAttr{"Type"} eq "Class")
3971 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003972 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003973 if($Skip) {
3974 return ();
3975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003976 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003977 if(my $Algn = getAlgn($TypeId)) {
3978 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003980 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003981
3982 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3983 {
3984 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003985 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003986 {
3987 if(not isAnon($TypeAttr{"Name"})) {
3988 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3989 }
3990 }
3991 }
3992
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003993 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003994 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3995 {
3996 my @Entries = split(/\n/, $VTable);
3997 foreach (1 .. $#Entries)
3998 {
3999 my $Entry = $Entries[$_];
4000 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004001 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004002 }
4003 }
4004 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004005
4006 if($TypeAttr{"Type"} eq "Enum")
4007 {
4008 if(not $TypeAttr{"NameSpace"})
4009 {
4010 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4011 {
4012 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004013 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004014 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004015 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004016 "Header"=>$TypeAttr{"Header"}
4017 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004018 if(isAnon($TypeAttr{"Name"}))
4019 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004020 if($ExtraDump
4021 or is_target_header($TypeAttr{"Header"}, $Version))
4022 {
4023 %{$Constants{$Version}{$MName}} = (
4024 "Value" => $MVal,
4025 "Header" => $TypeAttr{"Header"}
4026 );
4027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004028 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004029 }
4030 }
4031 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004032 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004033 {
4034 if(defined $TypedefToAnon{$TypeId}) {
4035 $TypeAttr{"AnonTypedef"} = 1;
4036 }
4037 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004039 return %TypeAttr;
4040}
4041
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004042sub simplifyVTable($)
4043{
4044 my $Content = $_[0];
4045 if($Content=~s/ \[with (.+)]//)
4046 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4047 if(my @Elems = separate_Params($1, 0, 0))
4048 {
4049 foreach my $Elem (@Elems)
4050 {
4051 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4052 {
4053 my ($Arg, $Val) = ($1, $2);
4054
4055 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4056 $Content=~s/,\s*$Arg\b//g;
4057 }
4058 else {
4059 $Content=~s/\b$Arg\b/$Val/g;
4060 }
4061 }
4062 }
4063 }
4064 }
4065
4066 return $Content;
4067}
4068
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004069sub detect_lang($)
4070{
4071 my $TypeId = $_[0];
4072 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004073 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004074 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004075 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4076 }
4077 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004078 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004079 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004080 while($Fncs)
4081 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004082 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004083 return 1;
4084 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004085 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004086 }
4087 }
4088 return 0;
4089}
4090
4091sub setSpec($$)
4092{
4093 my ($TypeId, $TypeAttr) = @_;
4094 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4095 if($Info=~/\s+spec\s+/) {
4096 $TypeAttr->{"Spec"} = 1;
4097 }
4098}
4099
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004100sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004101{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004102 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004103 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004104 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004105 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004106 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004107 my $Pos = 0;
4108 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4109 {
4110 my ($Access, $BInfoId) = ($1, $2);
4111 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004112
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004113 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004114 { # class A<N>:public A<N-1>
4115 next;
4116 }
4117
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004118 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4119 if(not $CType or $CType eq "template_type_parm"
4120 or $CType eq "typename_type")
4121 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004122 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004124 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004125 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004126 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4127 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004128 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4130 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004131 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004132 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004133 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4135 }
4136 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004137 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004138 }
4139 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004140 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004141}
4142
4143sub getBinfClassId($)
4144{
4145 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4146 $Info=~/type[ ]*:[ ]*@(\d+) /;
4147 return $1;
4148}
4149
4150sub unmangledFormat($$)
4151{
4152 my ($Name, $LibVersion) = @_;
4153 $Name = uncover_typedefs($Name, $LibVersion);
4154 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4155 $Name=~s/\(\w+\)(\d)/$1/;
4156 return $Name;
4157}
4158
4159sub modelUnmangled($$)
4160{
4161 my ($InfoId, $Compiler) = @_;
4162 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4163 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4164 }
4165 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4166 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4167 $PureSignature = "~".$PureSignature;
4168 }
4169 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4170 {
4171 my (@Params, @ParamTypes) = ();
4172 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4173 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4174 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4175 }
4176 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4177 { # checking parameters
4178 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004179 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004180 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004181 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004182
4183 if($PName eq "this"
4184 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4185 {
4186 next;
4187 }
4188
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004189 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004190 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004191 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 }
4193 @ParamTypes = (@ParamTypes, $PTName);
4194 }
4195 if(@ParamTypes) {
4196 $PureSignature .= "(".join(", ", @ParamTypes).")";
4197 }
4198 else
4199 {
4200 if($Compiler eq "MSVC")
4201 {
4202 $PureSignature .= "(void)";
4203 }
4204 else
4205 { # GCC
4206 $PureSignature .= "()";
4207 }
4208 }
4209 $PureSignature = delete_keywords($PureSignature);
4210 }
4211 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4212 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004213 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004214 $PureSignature = $ClassName."::".$PureSignature;
4215 }
4216 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4217 $PureSignature = $NS."::".$PureSignature;
4218 }
4219 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4220 $PureSignature .= " const";
4221 }
4222 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4223 $PureSignature .= " volatile";
4224 }
4225 my $ShowReturn = 0;
4226 if($Compiler eq "MSVC"
4227 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4228 {
4229 $ShowReturn=1;
4230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004231 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4232 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004233 {
4234 $ShowReturn=1;
4235 }
4236 if($ShowReturn)
4237 { # mangled names for template function specializations include return value
4238 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4239 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004240 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004241 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4242 $PureSignature = $ReturnName." ".$PureSignature;
4243 }
4244 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004245 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004246}
4247
4248sub mangle_symbol($$$)
4249{ # mangling for simple methods
4250 # see gcc-4.6.0/gcc/cp/mangle.c
4251 my ($InfoId, $LibVersion, $Compiler) = @_;
4252 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4253 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4254 }
4255 my $Mangled = "";
4256 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004257 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004258 }
4259 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004260 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 }
4262 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4263}
4264
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004265sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004266{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004267 my ($InfoId, $LibVersion) = @_;
4268 return "";
4269}
4270
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004271sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004272{ # see gcc-4.6.0/gcc/cp/mangle.c
4273 my ($InfoId, $LibVersion) = @_;
4274 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004275 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004276 my %Repl = ();# SN_ replacements
4277 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4278 {
4279 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4280 if($MangledClass!~/\AN/) {
4281 $MangledClass = "N".$MangledClass;
4282 }
4283 else {
4284 $MangledClass=~s/E\Z//;
4285 }
4286 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4287 $MangledClass=~s/\AN/NV/;
4288 }
4289 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4290 $MangledClass=~s/\AN/NK/;
4291 }
4292 $Mangled .= $MangledClass;
4293 }
4294 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4295 { # mangled by name due to the absence of structured info
4296 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4297 if($MangledNS!~/\AN/) {
4298 $MangledNS = "N".$MangledNS;
4299 }
4300 else {
4301 $MangledNS=~s/E\Z//;
4302 }
4303 $Mangled .= $MangledNS;
4304 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004305 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004306 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004307 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004308 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004309 foreach (@TPos) {
4310 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4311 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004312 }
4313 elsif($TmplParams)
4314 { # remangling mode
4315 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004316 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004317 }
4318 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4319 $Mangled .= "C1";
4320 }
4321 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4322 $Mangled .= "D0";
4323 }
4324 elsif($ShortName)
4325 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004326 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4327 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004328 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004329 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004330 { # "const" global data is mangled as _ZL...
4331 $Mangled .= "L";
4332 }
4333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004334 if($ShortName=~/\Aoperator(\W.*)\Z/)
4335 {
4336 my $Op = $1;
4337 $Op=~s/\A[ ]+//g;
4338 if(my $OpMngl = $OperatorMangling{$Op}) {
4339 $Mangled .= $OpMngl;
4340 }
4341 else { # conversion operator
4342 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4343 }
4344 }
4345 else {
4346 $Mangled .= length($ShortName).$ShortName;
4347 }
4348 if(@TParams)
4349 { # templates
4350 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004351 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004352 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4353 }
4354 $Mangled .= "E";
4355 }
4356 if(not $ClassId and @TParams) {
4357 add_substitution($ShortName, \%Repl, 0);
4358 }
4359 }
4360 if($ClassId or $NameSpace) {
4361 $Mangled .= "E";
4362 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004363 if(@TParams)
4364 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004365 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004366 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4367 }
4368 }
4369 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4370 {
4371 my @Params = ();
4372 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4373 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4374 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4375 }
4376 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4377 { # checking parameters
4378 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4379 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4380 }
4381 if(not @Params) {
4382 $Mangled .= "v";
4383 }
4384 }
4385 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4386 $Mangled = write_stdcxx_substitution($Mangled);
4387 if($Mangled eq "_Z") {
4388 return "";
4389 }
4390 return $Mangled;
4391}
4392
4393sub correct_incharge($$$)
4394{
4395 my ($InfoId, $LibVersion, $Mangled) = @_;
4396 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4397 {
4398 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004399 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004400 }
4401 }
4402 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4403 {
4404 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004405 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004406 }
4407 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004408 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 }
4410 }
4411 return $Mangled;
4412}
4413
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004414sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004415{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004416 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004417 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004418 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004419 return $Name;
4420 }
4421 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004422 while(my $CPos = find_center($TParams, "<"))
4423 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004424 $TParams = substr($TParams, $CPos);
4425 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004426 if($TParams=~s/\A<(.+)>\Z/$1/) {
4427 $Name=~s/<\Q$TParams\E>\Z//;
4428 }
4429 else
4430 { # error
4431 $TParams = "";
4432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433 return ($Name, $TParams);
4434}
4435
4436sub get_sub_ns($)
4437{
4438 my $Name = $_[0];
4439 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004440 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004441 {
4442 push(@NS, substr($Name, 0, $CPos));
4443 $Name = substr($Name, $CPos);
4444 $Name=~s/\A:://;
4445 }
4446 return (join("::", @NS), $Name);
4447}
4448
4449sub mangle_ns($$$)
4450{
4451 my ($Name, $LibVersion, $Repl) = @_;
4452 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4453 {
4454 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4455 $Mangled=~s/\AN(.+)E\Z/$1/;
4456 return $Mangled;
4457
4458 }
4459 else
4460 {
4461 my ($MangledNS, $SubNS) = ("", "");
4462 ($SubNS, $Name) = get_sub_ns($Name);
4463 if($SubNS) {
4464 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4465 }
4466 $MangledNS .= length($Name).$Name;
4467 add_substitution($MangledNS, $Repl, 0);
4468 return $MangledNS;
4469 }
4470}
4471
4472sub mangle_param($$$)
4473{
4474 my ($PTid, $LibVersion, $Repl) = @_;
4475 my ($MPrefix, $Mangled) = ("", "");
4476 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004477 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004478 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004479 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004480 if(not $BaseType_Name) {
4481 return "";
4482 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004483 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004484 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004485 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4486 while($Suffix=~/(&|\*|const)\Z/)
4487 {
4488 if($Suffix=~s/[ ]*&\Z//) {
4489 $MPrefix .= "R";
4490 }
4491 if($Suffix=~s/[ ]*\*\Z//) {
4492 $MPrefix .= "P";
4493 }
4494 if($Suffix=~s/[ ]*const\Z//)
4495 {
4496 if($MPrefix=~/R|P/
4497 or $Suffix=~/&|\*/) {
4498 $MPrefix .= "K";
4499 }
4500 }
4501 if($Suffix=~s/[ ]*volatile\Z//) {
4502 $MPrefix .= "V";
4503 }
4504 #if($Suffix=~s/[ ]*restrict\Z//) {
4505 #$MPrefix .= "r";
4506 #}
4507 }
4508 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4509 $Mangled .= $Token;
4510 }
4511 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4512 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004513 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004514 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004515 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004516 foreach (@TPos) {
4517 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4518 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004519 }
4520 elsif($TmplParams)
4521 { # remangling mode
4522 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004523 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004524 }
4525 my $MangledNS = "";
4526 my ($SubNS, $SName) = get_sub_ns($ShortName);
4527 if($SubNS) {
4528 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4529 }
4530 $MangledNS .= length($SName).$SName;
4531 if(@TParams) {
4532 add_substitution($MangledNS, $Repl, 0);
4533 }
4534 $Mangled .= "N".$MangledNS;
4535 if(@TParams)
4536 { # templates
4537 $Mangled .= "I";
4538 foreach my $TParam (@TParams) {
4539 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4540 }
4541 $Mangled .= "E";
4542 }
4543 $Mangled .= "E";
4544 }
4545 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4546 {
4547 if($BaseType{"Type"} eq "MethodPtr") {
4548 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4549 }
4550 else {
4551 $Mangled .= "PF";
4552 }
4553 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4554 my @Params = keys(%{$BaseType{"Param"}});
4555 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4556 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4557 }
4558 if(not @Params) {
4559 $Mangled .= "v";
4560 }
4561 $Mangled .= "E";
4562 }
4563 elsif($BaseType{"Type"} eq "FieldPtr")
4564 {
4565 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4566 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4567 }
4568 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4569 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4570 {
4571 if($Mangled eq $Optimized)
4572 {
4573 if($ShortName!~/::/)
4574 { # remove "N ... E"
4575 if($MPrefix) {
4576 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4577 }
4578 else {
4579 $Mangled=~s/\AN(.+)E\Z/$1/g;
4580 }
4581 }
4582 }
4583 else {
4584 $Mangled = $Optimized;
4585 }
4586 }
4587 add_substitution($Mangled, $Repl, 1);
4588 return $Mangled;
4589}
4590
4591sub mangle_template_param($$$)
4592{ # types + literals
4593 my ($TParam, $LibVersion, $Repl) = @_;
4594 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4595 return mangle_param($TPTid, $LibVersion, $Repl);
4596 }
4597 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4598 { # class_name<1u>::method(...)
4599 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4600 }
4601 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4602 { # class_name<(signed char)1>::method(...)
4603 return "L".$IntrinsicMangling{$1}.$2."E";
4604 }
4605 elsif($TParam eq "true")
4606 { # class_name<true>::method(...)
4607 return "Lb1E";
4608 }
4609 elsif($TParam eq "false")
4610 { # class_name<true>::method(...)
4611 return "Lb0E";
4612 }
4613 else { # internal error
4614 return length($TParam).$TParam;
4615 }
4616}
4617
4618sub add_substitution($$$)
4619{
4620 my ($Value, $Repl, $Rec) = @_;
4621 if($Rec)
4622 { # subtypes
4623 my @Subs = ($Value);
4624 while($Value=~s/\A(R|P|K)//) {
4625 push(@Subs, $Value);
4626 }
4627 foreach (reverse(@Subs)) {
4628 add_substitution($_, $Repl, 0);
4629 }
4630 return;
4631 }
4632 return if($Value=~/\AS(\d*)_\Z/);
4633 $Value=~s/\AN(.+)E\Z/$1/g;
4634 return if(defined $Repl->{$Value});
4635 return if(length($Value)<=1);
4636 return if($StdcxxMangling{$Value});
4637 # check for duplicates
4638 my $Base = $Value;
4639 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4640 {
4641 my $Num = $Repl->{$Type};
4642 my $Replace = macro_mangle($Num);
4643 $Base=~s/\Q$Replace\E/$Type/;
4644 }
4645 if(my $OldNum = $Repl->{$Base})
4646 {
4647 $Repl->{$Value} = $OldNum;
4648 return;
4649 }
4650 my @Repls = sort {$b<=>$a} values(%{$Repl});
4651 if(@Repls) {
4652 $Repl->{$Value} = $Repls[0]+1;
4653 }
4654 else {
4655 $Repl->{$Value} = -1;
4656 }
4657 # register duplicates
4658 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004659 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004660 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4661 {
4662 next if($Base eq $Type);
4663 my $Num = $Repl->{$Type};
4664 my $Replace = macro_mangle($Num);
4665 $Base=~s/\Q$Type\E/$Replace/;
4666 $Repl->{$Base} = $Repl->{$Value};
4667 }
4668}
4669
4670sub macro_mangle($)
4671{
4672 my $Num = $_[0];
4673 if($Num==-1) {
4674 return "S_";
4675 }
4676 else
4677 {
4678 my $Code = "";
4679 if($Num<10)
4680 { # S0_, S1_, S2_, ...
4681 $Code = $Num;
4682 }
4683 elsif($Num>=10 and $Num<=35)
4684 { # SA_, SB_, SC_, ...
4685 $Code = chr(55+$Num);
4686 }
4687 else
4688 { # S10_, S11_, S12_
4689 $Code = $Num-26; # 26 is length of english alphabet
4690 }
4691 return "S".$Code."_";
4692 }
4693}
4694
4695sub write_stdcxx_substitution($)
4696{
4697 my $Mangled = $_[0];
4698 if($StdcxxMangling{$Mangled}) {
4699 return $StdcxxMangling{$Mangled};
4700 }
4701 else
4702 {
4703 my @Repls = keys(%StdcxxMangling);
4704 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4705 foreach my $MangledType (@Repls)
4706 {
4707 my $Replace = $StdcxxMangling{$MangledType};
4708 #if($Mangled!~/$Replace/) {
4709 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4710 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4711 #}
4712 }
4713 }
4714 return $Mangled;
4715}
4716
4717sub write_substitution($$)
4718{
4719 my ($Mangled, $Repl) = @_;
4720 if(defined $Repl->{$Mangled}
4721 and my $MnglNum = $Repl->{$Mangled}) {
4722 $Mangled = macro_mangle($MnglNum);
4723 }
4724 else
4725 {
4726 my @Repls = keys(%{$Repl});
4727 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4728 # FIXME: how to apply replacements? by num or by pos
4729 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4730 foreach my $MangledType (@Repls)
4731 {
4732 my $Replace = macro_mangle($Repl->{$MangledType});
4733 if($Mangled!~/$Replace/) {
4734 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4735 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4736 }
4737 }
4738 }
4739 return $Mangled;
4740}
4741
4742sub delete_keywords($)
4743{
4744 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004745 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004746 return $TypeName;
4747}
4748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004749sub uncover_typedefs($$)
4750{
4751 my ($TypeName, $LibVersion) = @_;
4752 return "" if(not $TypeName);
4753 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4754 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4755 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004756 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004757 while($TypeName_New ne $TypeName_Pre)
4758 {
4759 $TypeName_Pre = $TypeName_New;
4760 my $TypeName_Copy = $TypeName_New;
4761 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004762 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004763 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004764 if(not $Intrinsic_Keywords{$1}) {
4765 $Words{$1} = 1;
4766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004767 }
4768 foreach my $Word (keys(%Words))
4769 {
4770 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4771 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004772 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004773 if($BaseType_Name=~/\([\*]+\)/)
4774 { # FuncPtr
4775 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4776 {
4777 my $Type_Suffix = $1;
4778 $TypeName_New = $BaseType_Name;
4779 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004780 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004781 }
4782 }
4783 }
4784 else
4785 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004786 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004787 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004788 }
4789 }
4790 }
4791 }
4792 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4793}
4794
4795sub isInternal($)
4796{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004797 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4798 {
4799 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4800 {
4801 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4802 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4803 return 1;
4804 }
4805 }
4806 }
4807 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004808}
4809
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004810sub getDataVal($$)
4811{
4812 my ($InfoId, $TypeId) = @_;
4813 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4814 {
4815 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4816 {
4817 if(defined $LibInfo{$Version}{"info_type"}{$1}
4818 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004819 {
4820 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004821 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004822 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4823 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004824 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004825 if(my $Addr = getTreeAttr_Op($1)) {
4826 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004827 }
4828 }
4829 }
4830 }
4831 else {
4832 return getInitVal($1, $TypeId);
4833 }
4834 }
4835 }
4836 return undef;
4837}
4838
4839sub getInitVal($$)
4840{
4841 my ($InfoId, $TypeId) = @_;
4842 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4843 {
4844 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4845 {
4846 if($InfoType eq "integer_cst")
4847 {
4848 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004849 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004850 { # characters
4851 $Val = chr($Val);
4852 }
4853 return $Val;
4854 }
4855 elsif($InfoType eq "string_cst") {
4856 return getNodeStrCst($InfoId);
4857 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004858 elsif($InfoType eq "var_decl")
4859 {
4860 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4861 return $Name;
4862 }
4863 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004864 }
4865 }
4866 return undef;
4867}
4868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004869sub set_Class_And_Namespace($)
4870{
4871 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004872 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004873 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004874 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004875 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004876 my $NSInfoId = $1;
4877 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4878 {
4879 if($InfoType eq "namespace_decl") {
4880 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4881 }
4882 elsif($InfoType eq "record_type") {
4883 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4884 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004886 }
4887 }
4888 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4889 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004890 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004891 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004892 { # skip
4893 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004895 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004896
4897 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004898}
4899
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004900sub debugMangling($)
4901{
4902 my $LibVersion = $_[0];
4903 my %Mangled = ();
4904 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4905 {
4906 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4907 {
4908 if($Mngl=~/\A(_Z|\?)/) {
4909 $Mangled{$Mngl}=$InfoId;
4910 }
4911 }
4912 }
4913 translateSymbols(keys(%Mangled), $LibVersion);
4914 foreach my $Mngl (keys(%Mangled))
4915 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004916 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4917 my $U2 = $tr_name{$Mngl};
4918 if($U1 ne $U2) {
4919 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004920 }
4921 }
4922}
4923
4924sub linkSymbol($)
4925{ # link symbols from shared libraries
4926 # with the symbols from header files
4927 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004928 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004929 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004930 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4931 or $EMERGENCY_MODE_48)
4932 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4933 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03004934 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004935 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004936 {
4937 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4938 return correct_incharge($InfoId, $Version, $Mangled);
4939 }
4940 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004941 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004942 or not $BinaryOnly
4943 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004944 { # 1. --headers-only mode
4945 # 2. not mangled src-only symbols
4946 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4947 return $Mangled;
4948 }
4949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004950 }
4951 return "";
4952}
4953
4954sub setLanguage($$)
4955{
4956 my ($LibVersion, $Lang) = @_;
4957 if(not $UserLang) {
4958 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4959 }
4960}
4961
4962sub getSymbolInfo($)
4963{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004964 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004965 if(isInternal($InfoId)) {
4966 return;
4967 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004968 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4969 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004970 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4971 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004972 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004973 return;
4974 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004975 setFuncAccess($InfoId);
4976 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004977 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4978 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004979 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004980 return;
4981 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004982
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004983 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004984 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004985 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004986 if(not defined $TypeInfo{$Version}{$Return}
4987 or not $TypeInfo{$Version}{$Return}{"Name"})
4988 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004989 delete($SymbolInfo{$Version}{$InfoId});
4990 return;
4991 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004992 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004993 }
4994 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4995 {
4996 if(defined $MissedTypedef{$Version}{$Rid})
4997 {
4998 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4999 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5000 }
5001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005002 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005003 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5004 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005005 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005006 my $Orig = getFuncOrig($InfoId);
5007 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005008 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5009 {
5010 delete($SymbolInfo{$Version}{$InfoId});
5011 return;
5012 }
5013
5014 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005015 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005016 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005017 return;
5018 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005019
5020 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005021 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005022 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5023
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005024 my @TParams = getTParams($Orig, "Func");
5025 if(not @TParams)
5026 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005027 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005028 return;
5029 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005030 foreach my $Pos (0 .. $#TParams)
5031 {
5032 my $Val = $TParams[$Pos];
5033 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5034
5035 if($Tmpl)
5036 {
5037 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5038 {
5039 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5040 }
5041 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005042 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005043
5044 if($Tmpl)
5045 {
5046 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5047 {
5048 if($Pos>$#TParams)
5049 {
5050 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5051 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5052 }
5053 }
5054 }
5055
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005056 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5057 { # operator<< <T>, operator>> <T>
5058 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5059 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005060 if(@TParams) {
5061 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5062 }
5063 else {
5064 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5065 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005066 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005067 }
5068 else
5069 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005070 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005071 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005072 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5073 {
5074 if($OSgroup eq "windows")
5075 { # cut the offset
5076 $MnglName=~s/\@\d+\Z//g;
5077 }
5078 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5079
5080 # NOTE: mangling of some symbols may change depending on GCC version
5081 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5082 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5083 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005084
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005085 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005086 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005087 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005088 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005089 return;
5090 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005091 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005092 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005093 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005094 if($Skip)
5095 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005096 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005097 return;
5098 }
5099 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005100 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5101 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5102 }
5103
5104 if(set_Class_And_Namespace($InfoId))
5105 {
5106 delete($SymbolInfo{$Version}{$InfoId});
5107 return;
5108 }
5109
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005110 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5111 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005112 if(not defined $TypeInfo{$Version}{$ClassId}
5113 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005115 delete($SymbolInfo{$Version}{$InfoId});
5116 return;
5117 }
5118 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005119 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5120 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005122 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005123 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005124 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005126 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005127 }
5128 if($COMMON_LANGUAGE{$Version} eq "C++")
5129 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005130 # C++ or --headers-only mode
5131 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005132 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005133 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5134 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005135 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005136 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005137 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005138 if(my $Mangled = linkSymbol($InfoId)) {
5139 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005140 }
5141 }
5142 if($OStarget eq "windows")
5143 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005144 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005146 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005147 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005148 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005149 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005150 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005151 }
5152 }
5153 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005154 else
5155 { # not mangled in C
5156 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5157 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005158 if(not $CheckHeadersOnly
5159 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5160 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5161 {
5162 my $Incorrect = 0;
5163
5164 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5165 {
5166 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5167 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5168 { # mangled in the TU dump, but not mangled in the library
5169 $Incorrect = 1;
5170 }
5171 }
5172 else
5173 {
5174 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5175 { # all C++ functions are not mangled in the TU dump
5176 $Incorrect = 1;
5177 }
5178 }
5179 if($Incorrect)
5180 {
5181 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5182 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5183 }
5184 }
5185 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005186 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005187 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005188 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005189 return;
5190 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005191 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005192 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005193 { # identify virtual and pure virtual functions
5194 # NOTE: constructors cannot be virtual
5195 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5196 # in the TU dump, so taking it from the original symbol
5197 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5198 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5199 { # NOTE: D2 destructors are not present in a v-table
5200 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005203 if(isInline($InfoId)) {
5204 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005205 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005206 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005207 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005209 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5210 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005211 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005212 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005213 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005214 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005215 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005216 }
5217 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005218 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5219 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005220 if(not $ExtraDump)
5221 {
5222 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5223 { # non-target symbols
5224 delete($SymbolInfo{$Version}{$InfoId});
5225 return;
5226 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005229 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5230 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5231 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5232 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005234 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5235 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 return;
5238 }
5239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005240 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005241 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005242 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005243 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005244 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005245 return;
5246 }
5247 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 }
5250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5252 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5253 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005255 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5256 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005257 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005258 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005260 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 }
5262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 if(getFuncLink($InfoId) eq "Static") {
5264 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005266 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5267 {
5268 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5269 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005270 if($Unmangled=~/\.\_\d/)
5271 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005272 delete($SymbolInfo{$Version}{$InfoId});
5273 return;
5274 }
5275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005276 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005277
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005278 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5279 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005281 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5282 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005283 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005284
5285 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5286 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5287 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005288
5289 if($ExtraDump) {
5290 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5291 }
5292}
5293
5294sub guessHeader($)
5295{
5296 my $InfoId = $_[0];
5297 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5298 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5299 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5300 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5301 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5302 {
5303 if(get_filename($HPath) eq $Header)
5304 {
5305 my $HDir = get_filename(get_dirname($HPath));
5306 if($HDir ne "include"
5307 and $HDir=~/\A[a-z]+\Z/i) {
5308 return join_P($HDir, $Header);
5309 }
5310 }
5311 }
5312 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005313}
5314
5315sub isInline($)
5316{ # "body: undefined" in the tree
5317 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005318 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5319 {
5320 if($Info=~/ undefined /i) {
5321 return 0;
5322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005323 }
5324 return 1;
5325}
5326
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005327sub hasThrow($)
5328{
5329 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5330 {
5331 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5332 return getTreeAttr_Unql($1, "unql");
5333 }
5334 }
5335 return 1;
5336}
5337
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005338sub getTypeId($)
5339{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005340 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5341 {
5342 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5343 return $1;
5344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005345 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005346 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005347}
5348
5349sub setTypeMemb($$)
5350{
5351 my ($TypeId, $TypeAttr) = @_;
5352 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005353 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005354 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355 if($TypeType eq "Enum")
5356 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005357 my $MInfoId = getTreeAttr_Csts($TypeId);
5358 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005359 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005360 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5361 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005362 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005363 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5364 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005365 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366 }
5367 }
5368 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5369 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005370 my $MInfoId = getTreeAttr_Flds($TypeId);
5371 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005373 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5374 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005375 if(not $IType or $IType ne "field_decl")
5376 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005377
5378 if($IType eq "var_decl")
5379 { # static field
5380 $StaticFields = 1;
5381 }
5382
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005383 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005384 next;
5385 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005386 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005387 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005388 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005389 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 }
5391 if(not $StructMembName)
5392 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005393 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005395 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005396 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5397 if(isAnon($UnnamedTName))
5398 { # rename unnamed fields to unnamed0, unnamed1, ...
5399 $StructMembName = "unnamed".($UnnamedPos++);
5400 }
5401 }
5402 }
5403 if(not $StructMembName)
5404 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005405 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005406 next;
5407 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005408 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005409 if(defined $MissedTypedef{$Version}{$MembTypeId})
5410 {
5411 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5412 $MembTypeId = $AddedTid;
5413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005415
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005416 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5417 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005418 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005419 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005420 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5421 }
5422 if($MInfo=~/spec:\s*mutable /)
5423 { # mutable fields
5424 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005425 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005426 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005427 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5428 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005429 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005430 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005431 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 }
5433 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005434 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005435 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5436 { # template
5437 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5438 }
5439 else {
5440 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005442 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005443
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005444 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005445 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005446 }
5447 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005448
5449 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005450}
5451
5452sub setFuncParams($)
5453{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005454 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005455 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005456
5457 my $FType = getFuncType($InfoId);
5458
5459 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005460 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005461 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5462 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005463 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005464 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005465 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005467 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005468 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005471 else
5472 { # skip
5473 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005474 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005475 # skip "this"-parameter
5476 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005477 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005478 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005479 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005480 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005481 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5482 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5483 if(not $ParamName)
5484 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005485 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005487 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5488 {
5489 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5490 $ParamTypeId = $AddedTid;
5491 }
5492 }
5493 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005494 if(not $PType or $PType eq "Unknown") {
5495 return 1;
5496 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005497 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005498 if(not $PTName) {
5499 return 1;
5500 }
5501 if($PTName eq "void") {
5502 last;
5503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005505 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005506 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005507 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005508 $ParamInfoId = getNextElem($ParamInfoId);
5509 next;
5510 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005511 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005512
5513 if(my %Base = get_BaseType($ParamTypeId, $Version))
5514 {
5515 if(defined $Base{"Template"}) {
5516 return 1;
5517 }
5518 }
5519
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005520 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005521 if(my $Algn = getAlgn($ParamInfoId)) {
5522 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005524 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5525 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005526 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 }
5528 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005529 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005530 if($ParamName ne "this" or $FType ne "Method") {
5531 $PPos += 1;
5532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005533 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005534 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005535 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 }
5537 return 0;
5538}
5539
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005540sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005542 my ($InfoId, $Vtt_Pos) = @_;
5543 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005544 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005545 my $FType = getFuncType($InfoId);
5546
5547 if($FType eq "Method")
5548 {
5549 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005550 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005552 if(not $ParamListElemId)
5553 { # foo(...)
5554 return 1;
5555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005556 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005557 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005558 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005559 { # actual params: may differ from formal args
5560 # formal int*const
5561 # actual: int*
5562 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 {
5564 $Vtt_Pos=-1;
5565 $ParamListElemId = getNextElem($ParamListElemId);
5566 next;
5567 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005568 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5569 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005570 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 $HaveVoid = 1;
5572 last;
5573 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005574 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005575 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005576 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5577 {
5578 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5579 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5580 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005581 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005582 }
5583 }
5584 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5585 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005586 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005587 { # params
5588 if($OldId ne $ParamTypeId)
5589 {
5590 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5591 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5592
5593 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5594 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5595 }
5596 }
5597 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005598 }
5599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005600 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005601 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005602 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5603 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005604 if($PurpType eq "nop_expr")
5605 { # func ( const char* arg = (const char*)(void*)0 )
5606 $PurpId = getTreeAttr_Op($PurpId);
5607 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005608 my $Val = getInitVal($PurpId, $ParamTypeId);
5609 if(defined $Val) {
5610 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5611 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005612 }
5613 }
5614 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005615 if($Pos!=0 or $FType ne "Method") {
5616 $PPos += 1;
5617 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005618 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005619 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005620 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005621}
5622
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005623sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005624{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005625 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5626 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005627 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5628 return $1;
5629 }
5630 }
5631 return "";
5632}
5633
5634sub getTreeAttr_Chain($)
5635{
5636 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5637 {
5638 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5639 return $1;
5640 }
5641 }
5642 return "";
5643}
5644
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005645sub getTreeAttr_Unql($)
5646{
5647 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5648 {
5649 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5650 return $1;
5651 }
5652 }
5653 return "";
5654}
5655
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005656sub getTreeAttr_Scpe($)
5657{
5658 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5659 {
5660 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5661 return $1;
5662 }
5663 }
5664 return "";
5665}
5666
5667sub getTreeAttr_Type($)
5668{
5669 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5670 {
5671 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5672 return $1;
5673 }
5674 }
5675 return "";
5676}
5677
5678sub getTreeAttr_Name($)
5679{
5680 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5681 {
5682 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5683 return $1;
5684 }
5685 }
5686 return "";
5687}
5688
5689sub getTreeAttr_Mngl($)
5690{
5691 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5692 {
5693 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5694 return $1;
5695 }
5696 }
5697 return "";
5698}
5699
5700sub getTreeAttr_Prms($)
5701{
5702 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5703 {
5704 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5705 return $1;
5706 }
5707 }
5708 return "";
5709}
5710
5711sub getTreeAttr_Fncs($)
5712{
5713 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5714 {
5715 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5716 return $1;
5717 }
5718 }
5719 return "";
5720}
5721
5722sub getTreeAttr_Csts($)
5723{
5724 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5725 {
5726 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5727 return $1;
5728 }
5729 }
5730 return "";
5731}
5732
5733sub getTreeAttr_Purp($)
5734{
5735 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5736 {
5737 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5738 return $1;
5739 }
5740 }
5741 return "";
5742}
5743
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005744sub getTreeAttr_Op($)
5745{
5746 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5747 {
5748 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5749 return $1;
5750 }
5751 }
5752 return "";
5753}
5754
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005755sub getTreeAttr_Valu($)
5756{
5757 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5758 {
5759 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5760 return $1;
5761 }
5762 }
5763 return "";
5764}
5765
5766sub getTreeAttr_Flds($)
5767{
5768 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5769 {
5770 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5771 return $1;
5772 }
5773 }
5774 return "";
5775}
5776
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005777sub getTreeAttr_Binf($)
5778{
5779 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5780 {
5781 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5782 return $1;
5783 }
5784 }
5785 return "";
5786}
5787
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005788sub getTreeAttr_Args($)
5789{
5790 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5791 {
5792 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005793 return $1;
5794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005795 }
5796 return "";
5797}
5798
5799sub getTreeValue($)
5800{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005801 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5802 {
5803 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5804 return $1;
5805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005806 }
5807 return "";
5808}
5809
5810sub getTreeAccess($)
5811{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005812 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005813 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005814 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5815 {
5816 my $Access = $1;
5817 if($Access eq "prot") {
5818 return "protected";
5819 }
5820 elsif($Access eq "priv") {
5821 return "private";
5822 }
5823 }
5824 elsif($Info=~/ protected /)
5825 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005826 return "protected";
5827 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005828 elsif($Info=~/ private /)
5829 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005830 return "private";
5831 }
5832 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005833 return "public";
5834}
5835
5836sub setFuncAccess($)
5837{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005838 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005839 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005840 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005841 }
5842 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005843 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005844 }
5845}
5846
5847sub setTypeAccess($$)
5848{
5849 my ($TypeId, $TypeAttr) = @_;
5850 my $Access = getTreeAccess($TypeId);
5851 if($Access eq "protected") {
5852 $TypeAttr->{"Protected"} = 1;
5853 }
5854 elsif($Access eq "private") {
5855 $TypeAttr->{"Private"} = 1;
5856 }
5857}
5858
5859sub setFuncKind($)
5860{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005861 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5862 {
5863 if($Info=~/pseudo tmpl/) {
5864 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5865 }
5866 elsif($Info=~/ constructor /) {
5867 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5868 }
5869 elsif($Info=~/ destructor /) {
5870 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005872 }
5873}
5874
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005875sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005876{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005877 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5878 {
5879 if($Info=~/spec[ ]*:[ ]*pure /) {
5880 return "PureVirt";
5881 }
5882 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5883 return "Virt";
5884 }
5885 elsif($Info=~/ pure\s+virtual /)
5886 { # support for old GCC versions
5887 return "PureVirt";
5888 }
5889 elsif($Info=~/ virtual /)
5890 { # support for old GCC versions
5891 return "Virt";
5892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005893 }
5894 return "";
5895}
5896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897sub getFuncLink($)
5898{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005899 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5900 {
5901 if($Info=~/link[ ]*:[ ]*static /) {
5902 return "Static";
5903 }
5904 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005905 return $1;
5906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005907 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005908 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005909}
5910
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005911sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005912{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005913 my ($Symbol, $LibVersion) = @_;
5914 return "" if(not $Symbol or not $LibVersion);
5915 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5916 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005917 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005918 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5919 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5920 }
5921 }
5922 if($NS)
5923 {
5924 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5925 return $NS;
5926 }
5927 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005929 while($NS=~s/::[^:]+\Z//)
5930 {
5931 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5932 return $NS;
5933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005934 }
5935 }
5936 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005937
5938 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005939}
5940
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005941sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005942{
5943 my ($TypeName, $LibVersion) = @_;
5944 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005945 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005946 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005947 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5948 return $NS;
5949 }
5950 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005951 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005952 while($NS=~s/::[^:]+\Z//)
5953 {
5954 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5955 return $NS;
5956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005957 }
5958 }
5959 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005960 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005961}
5962
5963sub getNameSpace($)
5964{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005965 my $InfoId = $_[0];
5966 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005967 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005968 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005969 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005970 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005971 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005972 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5973 {
5974 my $NameSpace = getTreeStr($1);
5975 if($NameSpace eq "::")
5976 { # global namespace
5977 return "";
5978 }
5979 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5980 $NameSpace = $BaseNameSpace."::".$NameSpace;
5981 }
5982 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5983 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005984 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005985 else {
5986 return "";
5987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005988 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005989 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005990 { # inside data type
5991 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5992 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005996 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005997}
5998
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999sub getEnumMembVal($)
6000{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006001 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006002 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006003 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6004 {
6005 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6006 {
6007 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6008 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6009 return getTreeValue($1);
6010 }
6011 else
6012 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6013 return getTreeValue($1);
6014 }
6015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006016 }
6017 }
6018 return "";
6019}
6020
6021sub getSize($)
6022{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006023 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6024 {
6025 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6026 return getTreeValue($1);
6027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006028 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006029 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006030}
6031
6032sub getAlgn($)
6033{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006034 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6035 {
6036 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6037 return $1;
6038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006039 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006040 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006041}
6042
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006043sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006044{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006045 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6046 {
6047 if($Info=~/ bitfield /) {
6048 return getSize($_[0]);
6049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006051 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052}
6053
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006054sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006056 if(my $Chan = getTreeAttr_Chan($_[0])) {
6057 return $Chan;
6058 }
6059 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6060 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006062 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063}
6064
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006065sub registerHeader($$)
6066{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006067 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006068 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006069 return "";
6070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006071 if(is_abs($Header) and not -f $Header)
6072 { # incorrect absolute path
6073 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006075 if(skipHeader($Header, $LibVersion))
6076 { # skip
6077 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006078 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006079 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6080 {
6081 detect_header_includes($Header_Path, $LibVersion);
6082
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006083 if(defined $Tolerance and $Tolerance=~/3/)
6084 { # 3 - skip headers that include non-Linux headers
6085 if($OSgroup ne "windows")
6086 {
6087 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6088 {
6089 if(specificHeader($Inc, "windows")) {
6090 return "";
6091 }
6092 }
6093 }
6094 }
6095
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006096 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6097 { # redirect
6098 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6099 or skipHeader($RHeader_Path, $LibVersion))
6100 { # skip
6101 return "";
6102 }
6103 $Header_Path = $RHeader_Path;
6104 }
6105 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6106 { # skip
6107 return "";
6108 }
6109
6110 if(my $HName = get_filename($Header_Path))
6111 { # register
6112 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6113 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6114 }
6115
6116 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6117 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006118 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006119 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006120 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006121 }
6122
6123 if($CheckHeadersOnly
6124 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6125 { # /usr/include/c++/4.6.1/...
6126 $STDCXX_TESTING = 1;
6127 }
6128
6129 return $Header_Path;
6130 }
6131 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006132}
6133
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006134sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135{
6136 my ($Dir, $WithDeps, $LibVersion) = @_;
6137 $Dir=~s/[\/\\]+\Z//g;
6138 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006139 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006141 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006142 if($WithDeps)
6143 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006144 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6145 return;
6146 }
6147 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6148 $Mode = "DepsOnly";
6149 }
6150 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006151 else
6152 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006153 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6154 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6155 return;
6156 }
6157 }
6158 $Header_Dependency{$LibVersion}{$Dir} = 1;
6159 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6160 if($Mode eq "DepsOnly")
6161 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006162 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006163 $Header_Dependency{$LibVersion}{$Path} = 1;
6164 }
6165 return;
6166 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006167 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006168 {
6169 if($WithDeps)
6170 {
6171 my $SubDir = $Path;
6172 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6173 { # register all sub directories
6174 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6175 }
6176 }
6177 next if(is_not_header($Path));
6178 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006179 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006180 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006181 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6182 }
6183 }
6184 if(get_filename($Dir) eq "include")
6185 { # search for "lib/include/" directory
6186 my $LibDir = $Dir;
6187 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006188 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189 }
6190 }
6191}
6192
6193sub parse_redirect($$$)
6194{
6195 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 my @Errors = ();
6197 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6198 push(@Errors, $1);
6199 }
6200 my $Redirect = "";
6201 foreach (@Errors)
6202 {
6203 s/\s{2,}/ /g;
6204 if(/(only|must\ include
6205 |update\ to\ include
6206 |replaced\ with
6207 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006208 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006209 {
6210 $Redirect = $2;
6211 last;
6212 }
6213 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6214 {
6215 $Redirect = $2;
6216 last;
6217 }
6218 elsif(/this\ header\ should\ not\ be\ used
6219 |programs\ should\ not\ directly\ include
6220 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6221 |is\ not\ supported\ API\ for\ general\ use
6222 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006223 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006224 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6225 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6226 }
6227 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006228 if($Redirect)
6229 {
6230 $Redirect=~s/\A<//g;
6231 $Redirect=~s/>\Z//g;
6232 }
6233 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006234}
6235
6236sub parse_includes($$)
6237{
6238 my ($Content, $Path) = @_;
6239 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006240 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006241 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006242 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006243 my $Method = substr($Header, 0, 1, "");
6244 substr($Header, length($Header)-1, 1, "");
6245 $Header = path_format($Header, $OSgroup);
6246 if($Method eq "\"" or is_abs($Header))
6247 {
6248 if(-e join_P(get_dirname($Path), $Header))
6249 { # relative path exists
6250 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006251 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006252 else
6253 { # include "..." that doesn't exist is equal to include <...>
6254 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006257 else {
6258 $Includes{$Header} = 1;
6259 }
6260 }
6261 if($ExtraInfo)
6262 {
6263 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6264 { # FT_FREETYPE_H
6265 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006266 }
6267 }
6268 return \%Includes;
6269}
6270
6271sub ignore_path($)
6272{
6273 my $Path = $_[0];
6274 if($Path=~/\~\Z/)
6275 {# skipping system backup files
6276 return 1;
6277 }
6278 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6279 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6280 return 1;
6281 }
6282 return 0;
6283}
6284
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006285sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006286{
6287 my ($ArrRef, $W) = @_;
6288 return if(length($W)<2);
6289 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6290}
6291
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006292sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006293{
6294 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 $H1=~s/\.[a-z]+\Z//ig;
6297 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006298
6299 my $Hname1 = get_filename($H1);
6300 my $Hname2 = get_filename($H2);
6301 my $HDir1 = get_dirname($H1);
6302 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006303 my $Dirname1 = get_filename($HDir1);
6304 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006305
6306 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6307 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6308
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006309 if($_[0] eq $_[1]
6310 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006311 return 0;
6312 }
6313 elsif($H1=~/\A\Q$H2\E/) {
6314 return 1;
6315 }
6316 elsif($H2=~/\A\Q$H1\E/) {
6317 return -1;
6318 }
6319 elsif($HDir1=~/\Q$Hname1\E/i
6320 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006321 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322 return -1;
6323 }
6324 elsif($HDir2=~/\Q$Hname2\E/i
6325 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006326 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006327 return 1;
6328 }
6329 elsif($Hname1=~/\Q$Dirname1\E/i
6330 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006331 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 return -1;
6333 }
6334 elsif($Hname2=~/\Q$Dirname2\E/i
6335 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006336 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006337 return 1;
6338 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006339 elsif($Hname1=~/(config|lib|util)/i
6340 and $Hname2!~/(config|lib|util)/i)
6341 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006342 return -1;
6343 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006344 elsif($Hname2=~/(config|lib|util)/i
6345 and $Hname1!~/(config|lib|util)/i)
6346 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006347 return 1;
6348 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006349 else
6350 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006351 my $R1 = checkRelevance($H1);
6352 my $R2 = checkRelevance($H2);
6353 if($R1 and not $R2)
6354 { # libebook/e-book.h
6355 return -1;
6356 }
6357 elsif($R2 and not $R1)
6358 { # libebook/e-book.h
6359 return 1;
6360 }
6361 else
6362 {
6363 return (lc($H1) cmp lc($H2));
6364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006365 }
6366}
6367
6368sub searchForHeaders($)
6369{
6370 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006372 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006373 registerGccHeaders();
6374
6375 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6376 { # c++ standard include paths
6377 registerCppHeaders();
6378 }
6379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006380 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006381 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6382 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006383 {
6384 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006385 if($SystemRoot)
6386 {
6387 if(is_abs($Path)) {
6388 $Path = $SystemRoot.$Path;
6389 }
6390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 if(not -e $Path) {
6392 exitStatus("Access_Error", "can't access \'$Path\'");
6393 }
6394 elsif(-f $Path) {
6395 exitStatus("Access_Error", "\'$Path\' - not a directory");
6396 }
6397 elsif(-d $Path)
6398 {
6399 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006400 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006401 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6402 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006403 }
6404 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006405 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006406 }
6407 }
6408 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006409 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006410 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6411 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006413 # registering directories
6414 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6415 {
6416 next if(not -e $Path);
6417 $Path = get_abs_path($Path);
6418 $Path = path_format($Path, $OSgroup);
6419 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006420 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006421 }
6422 elsif(-f $Path)
6423 {
6424 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006425 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006426 and not $LocalIncludes{$Dir})
6427 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006428 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006429 # if(my $OutDir = get_dirname($Dir))
6430 # { # registering the outer directory
6431 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6432 # and not $LocalIncludes{$OutDir}) {
6433 # registerDir($OutDir, 0, $LibVersion);
6434 # }
6435 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006436 }
6437 }
6438 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006439
6440 # clean memory
6441 %RegisteredDirs = ();
6442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006443 # registering headers
6444 my $Position = 0;
6445 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6446 {
6447 if(is_abs($Dest) and not -e $Dest) {
6448 exitStatus("Access_Error", "can't access \'$Dest\'");
6449 }
6450 $Dest = path_format($Dest, $OSgroup);
6451 if(is_header($Dest, 1, $LibVersion))
6452 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006453 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006454 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6455 }
6456 }
6457 elsif(-d $Dest)
6458 {
6459 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006460 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006461 {
6462 next if(ignore_path($Path));
6463 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006464 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006465 push(@Registered, $HPath);
6466 }
6467 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006468 @Registered = sort {sortHeaders($a, $b)} @Registered;
6469 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 foreach my $Path (@Registered) {
6471 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6472 }
6473 }
6474 else {
6475 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6476 }
6477 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006478
6479 if(defined $Tolerance and $Tolerance=~/4/)
6480 { # 4 - skip headers included by others
6481 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6482 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006483 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006484 delete($Registered_Headers{$LibVersion}{$Path});
6485 }
6486 }
6487 }
6488
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006489 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6490 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006491 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006492 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006493 if(is_abs($Header) and not -f $Header) {
6494 exitStatus("Access_Error", "can't access file \'$Header\'");
6495 }
6496 $Header = path_format($Header, $OSgroup);
6497 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6498 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006499 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006500 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006501 }
6502 else {
6503 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006505 }
6506 }
6507 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6508 { # set relative paths (for duplicates)
6509 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6510 { # search for duplicates
6511 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6512 my $Prefix = get_dirname($FirstPath);
6513 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6514 { # detect a shortest distinguishing prefix
6515 my $NewPrefix = $1;
6516 my %Identity = ();
6517 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6518 {
6519 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6520 $Identity{$Path} = $1;
6521 }
6522 }
6523 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006524 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006525 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6526 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6527 }
6528 last;
6529 }
6530 $Prefix = $NewPrefix; # increase prefix
6531 }
6532 }
6533 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006534
6535 # clean memory
6536 %HeaderName_Paths = ();
6537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006538 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6539 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006540 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006541 my ($Pos, $PairPos) = (-1, -1);
6542 my ($Path, $PairPath) = ();
6543 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6544 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6545 foreach my $Header_Path (@Paths)
6546 {
6547 if(get_filename($Header_Path) eq $PairName)
6548 {
6549 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6550 $PairPath = $Header_Path;
6551 }
6552 if(get_filename($Header_Path) eq $HeaderName)
6553 {
6554 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6555 $Path = $Header_Path;
6556 }
6557 }
6558 if($PairPos!=-1 and $Pos!=-1
6559 and int($PairPos)<int($Pos))
6560 {
6561 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6562 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6563 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6564 }
6565 }
6566 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6567 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6568 }
6569}
6570
6571sub detect_real_includes($$)
6572{
6573 my ($AbsPath, $LibVersion) = @_;
6574 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6575 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6576 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6577 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6578 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006579 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6580
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006581 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6582 return () if(not $Path);
6583 open(PREPROC, $Path);
6584 while(<PREPROC>)
6585 {
6586 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6587 {
6588 my $Include = path_format($1, $OSgroup);
6589 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6590 next;
6591 }
6592 if($Include eq $AbsPath) {
6593 next;
6594 }
6595 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6596 }
6597 }
6598 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006599 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6600}
6601
6602sub detect_header_includes($$)
6603{
6604 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006605 return if(not $LibVersion or not $Path);
6606 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6607 return;
6608 }
6609 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6610
6611 if(not -e $Path) {
6612 return;
6613 }
6614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006615 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006616 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6617 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006618 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006619 {
6620 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006621 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006622 }
6623 if($RedirectPath ne $Path) {
6624 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6625 }
6626 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006627 else
6628 { # can't find
6629 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006631 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006632 if(my $Inc = parse_includes($Content, $Path))
6633 {
6634 foreach my $Include (keys(%{$Inc}))
6635 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006636 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006637
6638 if(defined $Tolerance and $Tolerance=~/4/)
6639 {
6640 if(my $HPath = identifyHeader($Include, $LibVersion))
6641 {
6642 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6643 }
6644 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006647}
6648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006649sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006650{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006651 my $Path = $_[0];
6652 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006653 if($OStarget eq "symbian")
6654 {
6655 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6656 { # epoc32/include/libc/{stdio, ...}.h
6657 return 1;
6658 }
6659 }
6660 else
6661 {
6662 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6663 { # /usr/include/{stdio, ...}.h
6664 return 1;
6665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 return 0;
6668}
6669
6670sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006671{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006672 my $Dir = $_[0];
6673 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006674 if($OStarget eq "symbian")
6675 {
6676 if(get_filename($OutDir) eq "libc"
6677 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6678 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6679 return 1;
6680 }
6681 }
6682 else
6683 { # linux
6684 if($OutDir eq "/usr/include"
6685 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6686 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6687 return 1;
6688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006689 }
6690 return 0;
6691}
6692
6693sub detect_recursive_includes($$)
6694{
6695 my ($AbsPath, $LibVersion) = @_;
6696 return () if(not $AbsPath);
6697 if(isCyclical(\@RecurInclude, $AbsPath)) {
6698 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6699 }
6700 my ($AbsDir, $Name) = separate_path($AbsPath);
6701 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006702 { # system GLIBC internals
6703 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704 }
6705 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6706 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6707 }
6708 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006709
6710 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6711 { # skip /usr/include/c++/*/ headers
6712 return () if(not $ExtraInfo);
6713 }
6714
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006715 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006716 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006717 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006718 { # check "real" (non-"model") include paths
6719 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6720 pop(@RecurInclude);
6721 return @Paths;
6722 }
6723 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6724 detect_header_includes($AbsPath, $LibVersion);
6725 }
6726 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6727 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006728 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006730 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006731 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006732 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006733 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006734 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006735 }
6736 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006737 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006738 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006739 { # search for the nearest header
6740 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006741 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006742 if(-f $Candidate) {
6743 $HPath = $Candidate;
6744 }
6745 }
6746 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006747 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006748 }
6749 next if(not $HPath);
6750 if($HPath eq $AbsPath) {
6751 next;
6752 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006753
6754 if($Debug)
6755 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006756# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6757# {
6758# print STDERR "$AbsPath -> $HPath\n";
6759# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006760 }
6761
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006762 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6763 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006764 { # only include <...>, skip include "..." prefixes
6765 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6766 }
6767 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6768 {
6769 if($IncPath eq $AbsPath) {
6770 next;
6771 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006772 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6773 if($RIncType==-1)
6774 { # include "..."
6775 $RIncType = $IncType;
6776 }
6777 elsif($RIncType==2)
6778 {
6779 if($IncType!=-1) {
6780 $RIncType = $IncType;
6781 }
6782 }
6783 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006784 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6785 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6786 }
6787 }
6788 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6789 {
6790 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6791 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6792 { # distinguish math.h from glibc and math.h from the tested library
6793 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6794 last;
6795 }
6796 }
6797 }
6798 pop(@RecurInclude);
6799 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6800}
6801
6802sub find_in_framework($$$)
6803{
6804 my ($Header, $Framework, $LibVersion) = @_;
6805 return "" if(not $Header or not $Framework or not $LibVersion);
6806 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6807 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6808 }
6809 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6810 {
6811 if(get_filename($Dependency) eq $Framework
6812 and -f get_dirname($Dependency)."/".$Header) {
6813 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6814 }
6815 }
6816 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6817}
6818
6819sub find_in_defaults($)
6820{
6821 my $Header = $_[0];
6822 return "" if(not $Header);
6823 if(defined $Cache{"find_in_defaults"}{$Header}) {
6824 return $Cache{"find_in_defaults"}{$Header};
6825 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006826 foreach my $Dir (@DefaultIncPaths,
6827 @DefaultGccPaths,
6828 @DefaultCppPaths,
6829 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006830 {
6831 next if(not $Dir);
6832 if(-f $Dir."/".$Header) {
6833 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6834 }
6835 }
6836 return ($Cache{"find_in_defaults"}{$Header}="");
6837}
6838
6839sub cmp_paths($$)
6840{
6841 my ($Path1, $Path2) = @_;
6842 my @Parts1 = split(/[\/\\]/, $Path1);
6843 my @Parts2 = split(/[\/\\]/, $Path2);
6844 foreach my $Num (0 .. $#Parts1)
6845 {
6846 my $Part1 = $Parts1[$Num];
6847 my $Part2 = $Parts2[$Num];
6848 if($GlibcDir{$Part1}
6849 and not $GlibcDir{$Part2}) {
6850 return 1;
6851 }
6852 elsif($GlibcDir{$Part2}
6853 and not $GlibcDir{$Part1}) {
6854 return -1;
6855 }
6856 elsif($Part1=~/glib/
6857 and $Part2!~/glib/) {
6858 return 1;
6859 }
6860 elsif($Part1!~/glib/
6861 and $Part2=~/glib/) {
6862 return -1;
6863 }
6864 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6865 return $CmpRes;
6866 }
6867 }
6868 return 0;
6869}
6870
6871sub checkRelevance($)
6872{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006873 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006874 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006875
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006876 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006877 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006878 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006879
6880 my $Name = lc(get_filename($Path));
6881 my $Dir = lc(get_dirname($Path));
6882
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006883 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006884
6885 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006887 my $Len = length($Token);
6888 next if($Len<=1);
6889 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6890 { # include/evolution-data-server-1.4/libebook/e-book.h
6891 return 1;
6892 }
6893 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006894 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006895 return 1;
6896 }
6897 }
6898 return 0;
6899}
6900
6901sub checkFamily(@)
6902{
6903 my @Paths = @_;
6904 return 1 if($#Paths<=0);
6905 my %Prefix = ();
6906 foreach my $Path (@Paths)
6907 {
6908 if($SystemRoot) {
6909 $Path = cut_path_prefix($Path, $SystemRoot);
6910 }
6911 if(my $Dir = get_dirname($Path))
6912 {
6913 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6914 $Prefix{$Dir} += 1;
6915 $Prefix{get_dirname($Dir)} += 1;
6916 }
6917 }
6918 foreach (sort keys(%Prefix))
6919 {
6920 if(get_depth($_)>=3
6921 and $Prefix{$_}==$#Paths+1) {
6922 return 1;
6923 }
6924 }
6925 return 0;
6926}
6927
6928sub isAcceptable($$$)
6929{
6930 my ($Header, $Candidate, $LibVersion) = @_;
6931 my $HName = get_filename($Header);
6932 if(get_dirname($Header))
6933 { # with prefix
6934 return 1;
6935 }
6936 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6937 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6938 return 1;
6939 }
6940 if(checkRelevance($Candidate))
6941 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6942 return 1;
6943 }
6944 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6945 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6946 # /usr/include/qt4/Qt/qsslconfiguration.h
6947 return 1;
6948 }
6949 if($OStarget eq "symbian")
6950 {
6951 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6952 return 1;
6953 }
6954 }
6955 return 0;
6956}
6957
6958sub isRelevant($$$)
6959{ # disallow to search for "abstract" headers in too deep directories
6960 my ($Header, $Candidate, $LibVersion) = @_;
6961 my $HName = get_filename($Header);
6962 if($OStarget eq "symbian")
6963 {
6964 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6965 return 0;
6966 }
6967 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006968 if($OStarget ne "bsd")
6969 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006970 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6971 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6972 return 0;
6973 }
6974 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006975 if($OStarget ne "windows")
6976 {
6977 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6978 { # skip /usr/include/wine/msvcrt
6979 return 0;
6980 }
6981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006982 if(not get_dirname($Header)
6983 and $Candidate=~/[\/\\]wx[\/\\]/)
6984 { # do NOT search in system /wx/ directory
6985 # for headers without a prefix: sstream.h
6986 return 0;
6987 }
6988 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6989 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6990 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6991 return 0;
6992 }
6993 if($Candidate=~/[\/\\]asm-/
6994 and (my $Arch = getArch($LibVersion)) ne "unknown")
6995 { # arch-specific header files
6996 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6997 {# skip ../asm-arm/ if using x86 architecture
6998 return 0;
6999 }
7000 }
7001 my @Candidates = getSystemHeaders($HName, $LibVersion);
7002 if($#Candidates==1)
7003 { # unique header
7004 return 1;
7005 }
7006 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7007 if($#SCandidates==1)
7008 { # unique name
7009 return 1;
7010 }
7011 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7012 if(get_depth($Candidate)-$SystemDepth>=5)
7013 { # abstract headers in too deep directories
7014 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7015 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7016 return 0;
7017 }
7018 }
7019 if($Header eq "parser.h"
7020 and $Candidate!~/\/libxml2\//)
7021 { # select parser.h from xml2 library
7022 return 0;
7023 }
7024 if(not get_dirname($Header)
7025 and keys(%{$SystemHeaders{$HName}})>=3)
7026 { # many headers with the same name
7027 # like thread.h included without a prefix
7028 if(not checkFamily(@Candidates)) {
7029 return 0;
7030 }
7031 }
7032 return 1;
7033}
7034
7035sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007036{ # cache function
7037 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7038 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7039 }
7040 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7041}
7042
7043sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007044{
7045 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007046 if(-f $Header) {
7047 return $Header;
7048 }
7049 if(is_abs($Header) and not -f $Header)
7050 { # incorrect absolute path
7051 return "";
7052 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007053 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007054 { # too abstract configuration headers
7055 return "";
7056 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007057 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007058 if($OSgroup ne "windows")
7059 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007060 if(defined $WinHeaders{lc($HName)}
7061 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007062 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007063 return "";
7064 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007065 }
7066 if($OSgroup ne "macos")
7067 {
7068 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007069 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007070 return "";
7071 }
7072 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007073
7074 if(defined $ObsoleteHeaders{$HName})
7075 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007076 return "";
7077 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007078 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7079 {
7080 if(defined $AlienHeaders{$HName}
7081 or defined $AlienHeaders{$Header})
7082 { # alien headers from other systems
7083 return "";
7084 }
7085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007086
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007087 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007088 { # search in default paths
7089 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007090 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007091 }
7092 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007093 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007094 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007095 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007096 }
7097 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7098 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7099 {
7100 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007101 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007102 }
7103 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007104 # error
7105 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007106}
7107
7108sub getSystemHeaders($$)
7109{
7110 my ($Header, $LibVersion) = @_;
7111 my @Candidates = ();
7112 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7113 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007114 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007115 next;
7116 }
7117 push(@Candidates, $Candidate);
7118 }
7119 return @Candidates;
7120}
7121
7122sub cut_path_prefix($$)
7123{
7124 my ($Path, $Prefix) = @_;
7125 return $Path if(not $Prefix);
7126 $Prefix=~s/[\/\\]+\Z//;
7127 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7128 return $Path;
7129}
7130
7131sub is_default_include_dir($)
7132{
7133 my $Dir = $_[0];
7134 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007135 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007136}
7137
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007138sub identifyHeader($$)
7139{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007140 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007141 if(not $Header) {
7142 return "";
7143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007144 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007145 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7146 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007147 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007148 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007149}
7150
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007152{ # search for header by absolute path, relative path or name
7153 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007154 if(-f $Header)
7155 { # it's relative or absolute path
7156 return get_abs_path($Header);
7157 }
7158 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7159 and my $HeaderDir = find_in_defaults($Header))
7160 { # search for libc headers in the /usr/include
7161 # for non-libc target library before searching
7162 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007163 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007164 }
7165 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7166 { # search in the target library paths
7167 return $Path;
7168 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007169 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 { # search in the internal GCC include paths
7171 return $DefaultGccHeader{$Header};
7172 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007173 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007174 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007175 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007176 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007177 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007178 { # search in the default G++ include paths
7179 return $DefaultCppHeader{$Header};
7180 }
7181 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7182 { # search everywhere in the system
7183 return $AnyPath;
7184 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007185 elsif($OSgroup eq "macos")
7186 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7187 if(my $Dir = get_dirname($Header))
7188 {
7189 my $RelPath = "Headers\/".get_filename($Header);
7190 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007191 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007192 }
7193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007194 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007195 # cannot find anything
7196 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197}
7198
7199sub getLocation($)
7200{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007201 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7202 {
7203 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007204 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007207 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007208}
7209
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007210sub getNameByInfo($)
7211{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007212 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007213 {
7214 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7215 {
7216 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7217 {
7218 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7219 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007220 my $Str = $1;
7221 if($CppMode{$Version}
7222 and $Str=~/\Ac99_(.+)\Z/)
7223 {
7224 if($CppKeywords_A{$1}) {
7225 $Str=$1;
7226 }
7227 }
7228 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007229 }
7230 }
7231 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007232 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007233 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007234}
7235
7236sub getTreeStr($)
7237{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007238 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007240 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7241 {
7242 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007243 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007244 and $Str=~/\Ac99_(.+)\Z/)
7245 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007246 if($CppKeywords_A{$1}) {
7247 $Str=$1;
7248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007249 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007250 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007252 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007253 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254}
7255
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007256sub getFuncShortName($)
7257{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007258 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007260 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007261 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007262 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007263 {
7264 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7265 {
7266 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7267 return "operator ".$RName;
7268 }
7269 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007270 }
7271 else
7272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007273 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7274 {
7275 if(my $Ind = $Operator_Indication{$1}) {
7276 return "operator".$Ind;
7277 }
7278 elsif(not $UnknownOperator{$1})
7279 {
7280 printMsg("WARNING", "unknown operator $1");
7281 $UnknownOperator{$1} = 1;
7282 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007283 }
7284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007285 }
7286 else
7287 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007288 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7289 return getTreeStr($1);
7290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007291 }
7292 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007293 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007294}
7295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007296sub getFuncReturn($)
7297{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007298 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7299 {
7300 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7301 {
7302 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7303 return $1;
7304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305 }
7306 }
7307 return "";
7308}
7309
7310sub getFuncOrig($)
7311{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007312 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7313 {
7314 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7315 return $1;
7316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007317 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007318 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007319}
7320
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321sub unmangleArray(@)
7322{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007323 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007324 { # MSVC mangling
7325 my $UndNameCmd = get_CmdPath("undname");
7326 if(not $UndNameCmd) {
7327 exitStatus("Not_Found", "can't find \"undname\"");
7328 }
7329 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007330 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331 }
7332 else
7333 { # GCC mangling
7334 my $CppFiltCmd = get_CmdPath("c++filt");
7335 if(not $CppFiltCmd) {
7336 exitStatus("Not_Found", "can't find c++filt in PATH");
7337 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007338 if(not defined $CPPFILT_SUPPORT_FILE)
7339 {
7340 my $Info = `$CppFiltCmd -h 2>&1`;
7341 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7342 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007343 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007344 if($CPPFILT_SUPPORT_FILE)
7345 { # new versions of c++filt can take a file
7346 if($#_>$MAX_CPPFILT_FILE_SIZE)
7347 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7348 # this is fixed in the oncoming version of Binutils
7349 my @Half = splice(@_, 0, ($#_+1)/2);
7350 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007352 else
7353 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007354 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7355 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7356 if($?==139)
7357 { # segmentation fault
7358 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7359 }
7360 return split(/\n/, $Res);
7361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 }
7363 else
7364 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007365 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7366 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367 my @Half = splice(@_, 0, ($#_+1)/2);
7368 return (unmangleArray(@Half), unmangleArray(@_))
7369 }
7370 else
7371 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007372 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007373 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7374 if($?==139)
7375 { # segmentation fault
7376 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7377 }
7378 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007379 }
7380 }
7381 }
7382}
7383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007384sub get_ChargeLevel($$)
7385{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007386 my ($Symbol, $LibVersion) = @_;
7387 return "" if($Symbol!~/\A(_Z|\?)/);
7388 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7389 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007390 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007391 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007392 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007393 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007394 return "[in-charge]";
7395 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007396 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 return "[not-in-charge]";
7398 }
7399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007400 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007402 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007403 return "[in-charge]";
7404 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007405 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 return "[not-in-charge]";
7407 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007408 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 return "[in-charge-deleting]";
7410 }
7411 }
7412 }
7413 else
7414 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007415 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 return "[in-charge]";
7417 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007418 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 return "[not-in-charge]";
7420 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007421 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007422 return "[in-charge]";
7423 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007424 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007425 return "[not-in-charge]";
7426 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007427 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007428 return "[in-charge-deleting]";
7429 }
7430 }
7431 return "";
7432}
7433
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007434sub get_Signature_M($$)
7435{
7436 my ($Symbol, $LibVersion) = @_;
7437 my $Signature_M = $tr_name{$Symbol};
7438 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7439 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007440 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007441 }
7442 return $Signature_M;
7443}
7444
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007445sub get_Signature($$)
7446{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007447 my ($Symbol, $LibVersion) = @_;
7448 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7449 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007451 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007452 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007453
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007454 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007455
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007456 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007458 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7459 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007460 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7461 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007462
7463 if(index($Symbol, "_ZTV")==0) {
7464 return "vtable for $ClassName [data]";
7465 }
7466
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007467 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007468 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7469 $Signature .= "~";
7470 }
7471 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007473 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007474 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 }
7476 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007477 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007479 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7480 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007482 else
7483 {
7484 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 }
7486 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007487 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007489 if($Pos eq "") {
7490 next;
7491 }
7492
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007493 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007494 if(not $ParamTypeId) {
7495 next;
7496 }
7497
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007498 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499 if(not $ParamTypeName) {
7500 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7501 }
7502 foreach my $Typedef (keys(%ChangedTypedef))
7503 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007504 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7505 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007507 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007508 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7509 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007510 if($ParamName eq "this"
7511 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007512 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007513 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007514 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007515 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007516 }
7517 else {
7518 push(@ParamArray, $ParamTypeName);
7519 }
7520 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007521 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7522 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007523 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 }
7525 else
7526 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007527 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007529 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007531 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007532 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7533 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007534 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007536 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7537 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007538 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007540 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7541 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007542 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007543 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 }
7545 }
7546 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007547 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007548 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007549 }
7550 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007551 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007553 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007554}
7555
7556sub create_member_decl($$)
7557{
7558 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007559 if($TName=~/\([\*]+\)/)
7560 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7562 return $TName;
7563 }
7564 else
7565 {
7566 my @ArraySizes = ();
7567 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7568 push(@ArraySizes, $1);
7569 }
7570 return $TName." ".$Member.join("", @ArraySizes);
7571 }
7572}
7573
7574sub getFuncType($)
7575{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007576 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7577 {
7578 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7579 {
7580 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7581 {
7582 if($Type eq "method_type") {
7583 return "Method";
7584 }
7585 elsif($Type eq "function_type") {
7586 return "Function";
7587 }
7588 else {
7589 return "Other";
7590 }
7591 }
7592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007594 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595}
7596
7597sub getFuncTypeId($)
7598{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007599 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7600 {
7601 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7602 return $1;
7603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007605 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007606}
7607
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007608sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007609{ # "._N" or "$_N" in older GCC versions
7610 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007611}
7612
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007613sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007614{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007615 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7616 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007617 }
7618
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007619 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007620
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007621 if($_[1] ne "S")
7622 {
7623 $N=~s/\A[ ]+//g;
7624 $N=~s/[ ]+\Z//g;
7625 $N=~s/[ ]{2,}/ /g;
7626 }
7627
7628 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007629
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007630 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7631
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007632 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007633
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007634 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7635 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007636
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007637 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007639 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007640
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007641 if($_[1] eq "S")
7642 {
7643 if(index($N, "operator")!=-1) {
7644 $N=~s/\b(operator[ ]*)> >/$1>>/;
7645 }
7646 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007647
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007648 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007649
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007650 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007651}
7652
7653sub get_HeaderDeps($$)
7654{
7655 my ($AbsPath, $LibVersion) = @_;
7656 return () if(not $AbsPath or not $LibVersion);
7657 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7658 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7659 }
7660 my %IncDir = ();
7661 detect_recursive_includes($AbsPath, $LibVersion);
7662 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7663 {
7664 next if(not $HeaderPath);
7665 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7666 my $Dir = get_dirname($HeaderPath);
7667 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7668 {
7669 my $Dep = $Dir;
7670 if($Prefix)
7671 {
7672 if($OSgroup eq "windows")
7673 { # case insensitive seach on windows
7674 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7675 next;
7676 }
7677 }
7678 elsif($OSgroup eq "macos")
7679 { # seach in frameworks
7680 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7681 {
7682 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7683 {# frameworks
7684 my ($HFramework, $HName) = ($1, $2);
7685 $Dep = $HFramework;
7686 }
7687 else
7688 {# mismatch
7689 next;
7690 }
7691 }
7692 }
7693 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7694 { # Linux, FreeBSD
7695 next;
7696 }
7697 }
7698 if(not $Dep)
7699 { # nothing to include
7700 next;
7701 }
7702 if(is_default_include_dir($Dep))
7703 { # included by the compiler
7704 next;
7705 }
7706 if(get_depth($Dep)==1)
7707 { # too short
7708 next;
7709 }
7710 if(isLibcDir($Dep))
7711 { # do NOT include /usr/include/{sys,bits}
7712 next;
7713 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007714 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007715 }
7716 }
7717 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7718 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7719}
7720
7721sub sortIncPaths($$)
7722{
7723 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007724 if(not $ArrRef or $#{$ArrRef}<0) {
7725 return $ArrRef;
7726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007727 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7728 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007729 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007730 return $ArrRef;
7731}
7732
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007733sub sortDeps($$$)
7734{
7735 if($Header_Dependency{$_[2]}{$_[0]}
7736 and not $Header_Dependency{$_[2]}{$_[1]}) {
7737 return 1;
7738 }
7739 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7740 and $Header_Dependency{$_[2]}{$_[1]}) {
7741 return -1;
7742 }
7743 return 0;
7744}
7745
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007746sub join_P($$)
7747{
7748 my $S = "/";
7749 if($OSgroup eq "windows") {
7750 $S = "\\";
7751 }
7752 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007753}
7754
7755sub get_namespace_additions($)
7756{
7757 my $NameSpaces = $_[0];
7758 my ($Additions, $AddNameSpaceId) = ("", 1);
7759 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7760 {
7761 next if($SkipNameSpaces{$Version}{$NS});
7762 next if(not $NS or $NameSpaces->{$NS}==-1);
7763 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7764 next if($NS=~/\A__/i);
7765 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007766 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007767 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7768 my @NS_Parts = split(/::/, $NS);
7769 next if($#NS_Parts==-1);
7770 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7771 foreach my $NS_Part (@NS_Parts)
7772 {
7773 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7774 $TypeDecl_Suffix .= "}";
7775 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007776 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007777 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7778 $Additions.=" $TypeDecl\n $FuncDecl\n";
7779 $AddNameSpaceId+=1;
7780 }
7781 return $Additions;
7782}
7783
7784sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007785{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007786 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007787 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007788 if($Fmt eq "windows")
7789 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007790 $Path=~s/\//\\/g;
7791 $Path=lc($Path);
7792 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007793 else
7794 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007795 $Path=~s/\\/\//g;
7796 }
7797 return $Path;
7798}
7799
7800sub inc_opt($$)
7801{
7802 my ($Path, $Style) = @_;
7803 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007804 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007805 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007806 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007807 return "-I\"".path_format($Path, "unix")."\"";
7808 }
7809 elsif($OSgroup eq "macos"
7810 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007811 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007812 return "-F".esc(get_dirname($Path));
7813 }
7814 else {
7815 return "-I".esc($Path);
7816 }
7817 }
7818 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007819 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007820 }
7821 return "";
7822}
7823
7824sub platformSpecs($)
7825{
7826 my $LibVersion = $_[0];
7827 my $Arch = getArch($LibVersion);
7828 if($OStarget eq "symbian")
7829 { # options for GCCE compiler
7830 my %Symbian_Opts = map {$_=>1} (
7831 "-D__GCCE__",
7832 "-DUNICODE",
7833 "-fexceptions",
7834 "-D__SYMBIAN32__",
7835 "-D__MARM_INTERWORK__",
7836 "-D_UNICODE",
7837 "-D__S60_50__",
7838 "-D__S60_3X__",
7839 "-D__SERIES60_3X__",
7840 "-D__EPOC32__",
7841 "-D__MARM__",
7842 "-D__EABI__",
7843 "-D__MARM_ARMV5__",
7844 "-D__SUPPORT_CPP_EXCEPTIONS__",
7845 "-march=armv5t",
7846 "-mapcs",
7847 "-mthumb-interwork",
7848 "-DEKA2",
7849 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7850 );
7851 return join(" ", keys(%Symbian_Opts));
7852 }
7853 elsif($OSgroup eq "windows"
7854 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7855 { # add options to MinGW compiler
7856 # to simulate the MSVC compiler
7857 my %MinGW_Opts = map {$_=>1} (
7858 "-D_WIN32",
7859 "-D_STDCALL_SUPPORTED",
7860 "-D__int64=\"long long\"",
7861 "-D__int32=int",
7862 "-D__int16=short",
7863 "-D__int8=char",
7864 "-D__possibly_notnullterminated=\" \"",
7865 "-D__nullterminated=\" \"",
7866 "-D__nullnullterminated=\" \"",
7867 "-D__w64=\" \"",
7868 "-D__ptr32=\" \"",
7869 "-D__ptr64=\" \"",
7870 "-D__forceinline=inline",
7871 "-D__inline=inline",
7872 "-D__uuidof(x)=IID()",
7873 "-D__try=",
7874 "-D__except(x)=",
7875 "-D__declspec(x)=__attribute__((x))",
7876 "-D__pragma(x)=",
7877 "-D_inline=inline",
7878 "-D__forceinline=__inline",
7879 "-D__stdcall=__attribute__((__stdcall__))",
7880 "-D__cdecl=__attribute__((__cdecl__))",
7881 "-D__fastcall=__attribute__((__fastcall__))",
7882 "-D__thiscall=__attribute__((__thiscall__))",
7883 "-D_stdcall=__attribute__((__stdcall__))",
7884 "-D_cdecl=__attribute__((__cdecl__))",
7885 "-D_fastcall=__attribute__((__fastcall__))",
7886 "-D_thiscall=__attribute__((__thiscall__))",
7887 "-DSHSTDAPI_(x)=x",
7888 "-D_MSC_EXTENSIONS",
7889 "-DSECURITY_WIN32",
7890 "-D_MSC_VER=1500",
7891 "-D_USE_DECLSPECS_FOR_SAL",
7892 "-D__noop=\" \"",
7893 "-DDECLSPEC_DEPRECATED=\" \"",
7894 "-D__builtin_alignof(x)=__alignof__(x)",
7895 "-DSORTPP_PASS");
7896 if($Arch eq "x86") {
7897 $MinGW_Opts{"-D_M_IX86=300"}=1;
7898 }
7899 elsif($Arch eq "x86_64") {
7900 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7901 }
7902 elsif($Arch eq "ia64") {
7903 $MinGW_Opts{"-D_M_IA64=300"}=1;
7904 }
7905 return join(" ", keys(%MinGW_Opts));
7906 }
7907 return "";
7908}
7909
7910my %C_Structure = map {$_=>1} (
7911# FIXME: Can't separate union and struct data types before dumping,
7912# so it sometimes cause compilation errors for unknown reason
7913# when trying to declare TYPE* tmp_add_class_N
7914# This is a list of such structures + list of other C structures
7915 "sigval",
7916 "sigevent",
7917 "sigaction",
7918 "sigvec",
7919 "sigstack",
7920 "timeval",
7921 "timezone",
7922 "rusage",
7923 "rlimit",
7924 "wait",
7925 "flock",
7926 "stat",
7927 "_stat",
7928 "stat32",
7929 "_stat32",
7930 "stat64",
7931 "_stat64",
7932 "_stati64",
7933 "if_nameindex",
7934 "usb_device",
7935 "sigaltstack",
7936 "sysinfo",
7937 "timeLocale",
7938 "tcp_debug",
7939 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007940 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007941 "timespec",
7942 "random_data",
7943 "drand48_data",
7944 "_IO_marker",
7945 "_IO_FILE",
7946 "lconv",
7947 "sched_param",
7948 "tm",
7949 "itimerspec",
7950 "_pthread_cleanup_buffer",
7951 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007952 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007953 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007954 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007955 "sigcontext",
7956 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007957 # Mac
7958 "_timex",
7959 "_class_t",
7960 "_category_t",
7961 "_class_ro_t",
7962 "_protocol_t",
7963 "_message_ref_t",
7964 "_super_message_ref_t",
7965 "_ivar_t",
7966 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007967);
7968
7969sub getCompileCmd($$$)
7970{
7971 my ($Path, $Opt, $Inc) = @_;
7972 my $GccCall = $GCC_PATH;
7973 if($Opt) {
7974 $GccCall .= " ".$Opt;
7975 }
7976 $GccCall .= " -x ";
7977 if($OSgroup eq "macos") {
7978 $GccCall .= "objective-";
7979 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007980
7981 if($EMERGENCY_MODE_48)
7982 { # workaround for GCC 4.8 (C only)
7983 $GccCall .= "c++";
7984 }
7985 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007986 { # compile as "C++" header
7987 # to obtain complete dump using GCC 4.0
7988 $GccCall .= "c++-header";
7989 }
7990 else
7991 { # compile as "C++" source
7992 # GCC 3.3 cannot compile headers
7993 $GccCall .= "c++";
7994 }
7995 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007996 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007997 $GccCall .= " ".$Opts;
7998 }
7999 # allow extra qualifications
8000 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008001 $GccCall .= " -fpermissive";
8002 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008003 if($NoStdInc)
8004 {
8005 $GccCall .= " -nostdinc";
8006 $GccCall .= " -nostdinc++";
8007 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008008 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008009 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008010 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008011 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008012 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008013 if($Inc)
8014 { # include paths
8015 $GccCall .= " ".$Inc;
8016 }
8017 return $GccCall;
8018}
8019
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008020sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008021{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008022 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008023 my %HeaderElems = (
8024 # Types
8025 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008026 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008027 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8028 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008029 "time.h" => ["time_t"],
8030 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008031 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8032 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008033 "stdbool.h" => ["_Bool"],
8034 "rpc/xdr.h" => ["bool_t"],
8035 "in_systm.h" => ["n_long", "n_short"],
8036 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008037 "arpa/inet.h" => ["fw_src", "ip_src"],
8038 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008039 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008040 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008041 );
8042 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008043 foreach (keys(%HeaderElems))
8044 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008045 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008046 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008047 }
8048 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008049 my %Types = ();
8050 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8051 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008052 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008053 }
8054 if(keys(%Types))
8055 {
8056 my %AddHeaders = ();
8057 foreach my $Type (keys(%Types))
8058 {
8059 if(my $Header = $AutoPreamble{$Type})
8060 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008061 if(my $Path = identifyHeader($Header, $LibVersion))
8062 {
8063 if(skipHeader($Path, $LibVersion)) {
8064 next;
8065 }
8066 $Path = path_format($Path, $OSgroup);
8067 $AddHeaders{$Path}{"Type"} = $Type;
8068 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008069 }
8070 }
8071 }
8072 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008073 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008074 }
8075 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008076 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008077}
8078
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008079sub checkCTags($)
8080{
8081 my $Path = $_[0];
8082 if(not $Path) {
8083 return;
8084 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008085 my $CTags = undef;
8086
8087 if($OSgroup eq "bsd")
8088 { # use ectags on BSD
8089 $CTags = get_CmdPath("ectags");
8090 if(not $CTags) {
8091 printMsg("WARNING", "can't find \'ectags\' program");
8092 }
8093 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008094 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008095 $CTags = get_CmdPath("ctags");
8096 }
8097 if(not $CTags)
8098 {
8099 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008100 return;
8101 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008102
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008103 if($OSgroup ne "linux")
8104 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008105 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8106 if($Info!~/exuberant/i)
8107 {
8108 printMsg("WARNING", "incompatible version of \'ctags\' program");
8109 return;
8110 }
8111 }
8112
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008113 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008114 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008115 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008116 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008117 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008118 open(CTAGS, "<", $Out);
8119 while(my $Line = <CTAGS>)
8120 {
8121 chomp($Line);
8122 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008123 if(defined $Intrinsic_Keywords{$Name})
8124 { # noise
8125 next;
8126 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008127 if($Type eq "n")
8128 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008129 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008130 next;
8131 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008132 if(index($Scpe, "struct:")==0) {
8133 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008134 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008135 if(index($Scpe, "namespace:")==0)
8136 {
8137 if($Scpe=~s/\Anamespace://) {
8138 $Name = $Scpe."::".$Name;
8139 }
8140 }
8141 $TUnit_NameSpaces{$Version}{$Name} = 1;
8142 }
8143 elsif($Type eq "p")
8144 {
8145 if(not $Scpe or index($Scpe, "namespace:")==0) {
8146 $TUnit_Funcs{$Version}{$Name} = 1;
8147 }
8148 }
8149 elsif($Type eq "x")
8150 {
8151 if(not $Scpe or index($Scpe, "namespace:")==0) {
8152 $TUnit_Vars{$Version}{$Name} = 1;
8153 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008154 }
8155 }
8156 close(CTAGS);
8157}
8158
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008159sub preChange($$)
8160{
8161 my ($HeaderPath, $IncStr) = @_;
8162
8163 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8164 my $Content = undef;
8165
8166 if($OStarget eq "windows"
8167 and get_dumpmachine($GCC_PATH)=~/mingw/i
8168 and $MinGWMode{$Version}!=-1)
8169 { # modify headers to compile by MinGW
8170 if(not $Content)
8171 { # preprocessing
8172 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8173 }
8174 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8175 { # __asm { ... }
8176 $MinGWMode{$Version}=1;
8177 }
8178 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8179 { # comments after preprocessing
8180 $MinGWMode{$Version}=1;
8181 }
8182 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8183 { # 0xffui8
8184 $MinGWMode{$Version}=1;
8185 }
8186
8187 if($MinGWMode{$Version}) {
8188 printMsg("INFO", "Using MinGW compatibility mode");
8189 }
8190 }
8191
8192 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8193 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8194 { # rename C++ keywords in C code
8195 # disable this code by -cpp-compatible option
8196 if(not $Content)
8197 { # preprocessing
8198 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8199 }
8200 my $RegExp_C = join("|", keys(%CppKeywords_C));
8201 my $RegExp_F = join("|", keys(%CppKeywords_F));
8202 my $RegExp_O = join("|", keys(%CppKeywords_O));
8203
8204 my $Detected = undef;
8205
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008206 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*([\,\)\;\.\[]|\-\>|\:\s*\d))/$1$2c99_$3$4/g)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008207 { # MATCH:
8208 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008209 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008210 # unsigned private: 8;
8211 # DO NOT MATCH:
8212 # #pragma GCC visibility push(default)
8213 $CppMode{$Version} = 1;
8214 $Detected = "$1$2$3$4" if(not defined $Detected);
8215 }
8216 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8217 { # MATCH:
8218 # int delete(...);
8219 # int explicit(...);
8220 # DO NOT MATCH:
8221 # void operator delete(...)
8222 $CppMode{$Version} = 1;
8223 $Detected = "$1$2$3" if(not defined $Detected);
8224 }
8225 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8226 { # MATCH:
8227 # int bool;
8228 # DO NOT MATCH:
8229 # bool X;
8230 # return *this;
8231 # throw;
8232 $CppMode{$Version} = 1;
8233 $Detected = "$1$2$3" if(not defined $Detected);
8234 }
8235 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8236 { # MATCH:
8237 # int operator(...);
8238 # DO NOT MATCH:
8239 # int operator()(...);
8240 $CppMode{$Version} = 1;
8241 $Detected = "$1$2$3" if(not defined $Detected);
8242 }
8243 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8244 { # MATCH:
8245 # int foo(int operator);
8246 # int foo(int operator, int other);
8247 # DO NOT MATCH:
8248 # int operator,(...);
8249 $CppMode{$Version} = 1;
8250 $Detected = "$1$2$3" if(not defined $Detected);
8251 }
8252 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8253 { # MATCH:
8254 # int foo(gboolean *bool);
8255 # DO NOT MATCH:
8256 # void setTabEnabled(int index, bool);
8257 $CppMode{$Version} = 1;
8258 $Detected = "$1$2$3" if(not defined $Detected);
8259 }
8260 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8261 { # MATCH:
8262 # int foo(int* this);
8263 # int bar(int this);
8264 # int baz(int throw);
8265 # DO NOT MATCH:
8266 # foo(X, this);
8267 $CppMode{$Version} = 1;
8268 $Detected = "$1$2$3$4" if(not defined $Detected);
8269 }
8270 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8271 { # MATCH:
8272 # struct template {...};
8273 # extern template foo(...);
8274 $CppMode{$Version} = 1;
8275 $Detected = "$1$2" if(not defined $Detected);
8276 }
8277
8278 if($CppMode{$Version} == 1)
8279 {
8280 if($Debug)
8281 {
8282 $Detected=~s/\A\s+//g;
8283 printMsg("INFO", "Detected code: \"$Detected\"");
8284 }
8285 }
8286
8287 # remove typedef enum NAME NAME;
8288 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8289 my $N = 0;
8290 while($N<=$#FwdTypedefs-1)
8291 {
8292 my $S = $FwdTypedefs[$N];
8293 if($S eq $FwdTypedefs[$N+1])
8294 {
8295 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008296 $CppMode{$Version} = 1;
8297
8298 if($Debug) {
8299 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8300 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008301 }
8302 $N+=2;
8303 }
8304
8305 if($CppMode{$Version}==1) {
8306 printMsg("INFO", "Using C++ compatibility mode");
8307 }
8308 }
8309
8310 if($CppMode{$Version}==1
8311 or $MinGWMode{$Version}==1)
8312 {
8313 my $IPath = $TMP_DIR."/dump$Version.i";
8314 writeFile($IPath, $Content);
8315 return $IPath;
8316 }
8317
8318 return undef;
8319}
8320
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008321sub getDump()
8322{
8323 if(not $GCC_PATH) {
8324 exitStatus("Error", "internal error - GCC path is not set");
8325 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008326
8327 my @Headers = keys(%{$Registered_Headers{$Version}});
8328 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8329
8330 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8331
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008332 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008333 my $HeaderPath = $TmpHeaderPath;
8334
8335 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008336 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008337 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8338 {
8339 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008340 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008341 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008342 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008343 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8344 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008345 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008346 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008347 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008348 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8349 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008351 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008352 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008353
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008354 if($ExtraInfo)
8355 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008356 if($IncludeString) {
8357 writeFile($ExtraInfo."/include-string", $IncludeString);
8358 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008359 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8360 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008361
8362 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8363 {
8364 my $REDIR = "";
8365 foreach my $P1 (sort @Redirects) {
8366 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8367 }
8368 writeFile($ExtraInfo."/include-redirect", $REDIR);
8369 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008370 }
8371
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008372 if(not keys(%{$TargetHeaders{$Version}}))
8373 { # Target headers
8374 addTargetHeaders($Version);
8375 }
8376
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008377 # clean memory
8378 %RecursiveIncludes = ();
8379 %Header_Include_Prefix = ();
8380 %Header_Includes = ();
8381
8382 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008383 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008384 delete($Cache{"detect_header_includes"});
8385 delete($Cache{"selectSystemHeader"});
8386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008387 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008388 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8389 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008390
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008391 if($ExtraInfo)
8392 { # extra information for other tools
8393 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8394 }
8395
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008396 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008397 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008398 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008399
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008400 if($COMMON_LANGUAGE{$Version} eq "C++") {
8401 checkCTags($Pre);
8402 }
8403
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008404 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8405 { # try to correct the preprocessor output
8406 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008408
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008409 if($COMMON_LANGUAGE{$Version} eq "C++")
8410 { # add classes and namespaces to the dump
8411 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008412 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008413 or $MinGWMode{$Version}==1) {
8414 $CHdump .= " -fpreprocessed";
8415 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008416 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008417 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008418 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008419 chdir($ORIG_DIR);
8420 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8421 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008422 my $Content = readFile($ClassDump);
8423 foreach my $ClassInfo (split(/\n\n/, $Content))
8424 {
8425 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8426 {
8427 my $CName = $1;
8428 next if($CName=~/\A(__|_objc_|_opaque_)/);
8429 $TUnit_NameSpaces{$Version}{$CName} = -1;
8430 if($CName=~/\A[\w:]+\Z/)
8431 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008432 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 }
8434 if($CName=~/(\w[\w:]*)::/)
8435 { # namespaces
8436 my $NS = $1;
8437 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8438 $TUnit_NameSpaces{$Version}{$NS} = 1;
8439 }
8440 }
8441 }
8442 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8443 { # read v-tables (advanced approach)
8444 my ($CName, $VTable) = ($1, $2);
8445 $ClassVTable_Content{$Version}{$CName} = $VTable;
8446 }
8447 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008448 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8449 { # add user-defined namespaces
8450 $TUnit_NameSpaces{$Version}{$NS} = 1;
8451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008452 if($Debug)
8453 { # debug mode
8454 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008455 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008456 }
8457 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008458 }
8459
8460 # add namespaces and classes
8461 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8462 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008463 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008464 }
8465 # some GCC versions don't include class methods to the TU dump by default
8466 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008467 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008468 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8469 {
8470 next if($C_Structure{$CName});
8471 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008472 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008473 if(not $Force and $GCC_44
8474 and $OSgroup eq "linux")
8475 { # optimization for linux with GCC >= 4.4
8476 # disable this code by -force option
8477 if(index($CName, "::")!=-1)
8478 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008479 next;
8480 }
8481 }
8482 else
8483 {
8484 if($CName=~/\A(.+)::[^:]+\Z/
8485 and $TUnit_Classes{$Version}{$1})
8486 { # classes inside other classes
8487 next;
8488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008489 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008490 if(defined $TUnit_Funcs{$Version}{$CName})
8491 { # the same name for a function and type
8492 next;
8493 }
8494 if(defined $TUnit_Vars{$Version}{$CName})
8495 { # the same name for a variable and type
8496 next;
8497 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008498 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8499 }
8500 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008501 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008502 }
8503 }
8504 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8505 # create TU dump
8506 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008507 if($UserLang eq "C") {
8508 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8509 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008510 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008511 or $MinGWMode{$Version}==1) {
8512 $TUdump .= " -fpreprocessed";
8513 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008514 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008515 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8516 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008517 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008518 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008519 if($?)
8520 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008521 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008522 { # try to recompile
8523 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008524 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008525 and index($Errors, "c99_")!=-1
8526 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008527 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008528 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008529
8530 if($Debug)
8531 {
8532 # printMsg("INFO", $Errors);
8533 }
8534
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008535 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008536 resetLogging($Version);
8537 $TMP_DIR = tempdir(CLEANUP=>1);
8538 return getDump();
8539 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008540 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008541 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008542 { # add auto preamble headers and try again
8543 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008544 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008545 foreach my $Num (0 .. $#Headers)
8546 {
8547 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008548 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8549 {
8550 push_U($Include_Preamble{$Version}, $Path);
8551 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008552 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008553 }
8554 resetLogging($Version);
8555 $TMP_DIR = tempdir(CLEANUP=>1);
8556 return getDump();
8557 }
8558 elsif($Cpp0xMode{$Version}!=-1
8559 and ($Errors=~/\Q-std=c++0x\E/
8560 or $Errors=~/is not a class or namespace/))
8561 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008562 if(check_gcc($GCC_PATH, "4.6"))
8563 {
8564 $Cpp0xMode{$Version}=-1;
8565 printMsg("INFO", "Enabling c++0x mode");
8566 resetLogging($Version);
8567 $TMP_DIR = tempdir(CLEANUP=>1);
8568 $CompilerOptions{$Version} .= " -std=c++0x";
8569 return getDump();
8570 }
8571 else {
8572 printMsg("WARNING", "Probably c++0x construction detected");
8573 }
8574
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008575 }
8576 elsif($MinGWMode{$Version}==1)
8577 { # disable MinGW mode and try again
8578 $MinGWMode{$Version}=-1;
8579 resetLogging($Version);
8580 $TMP_DIR = tempdir(CLEANUP=>1);
8581 return getDump();
8582 }
8583 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008584 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008585 else {
8586 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008588 printMsg("ERROR", "some errors occurred when compiling headers");
8589 printErrorLog($Version);
8590 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008591 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008592 }
8593 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008594 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008595 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008596
8597 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8598 return $TUs[0];
8599 }
8600 else
8601 {
8602 my $Msg = "can't compile header(s)";
8603 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8604 $Msg .= "\nDid you install G++?";
8605 }
8606 exitStatus("Cannot_Compile", $Msg);
8607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008608}
8609
8610sub cmd_file($)
8611{
8612 my $Path = $_[0];
8613 return "" if(not $Path or not -e $Path);
8614 if(my $CmdPath = get_CmdPath("file")) {
8615 return `$CmdPath -b \"$Path\"`;
8616 }
8617 return "";
8618}
8619
8620sub getIncString($$)
8621{
8622 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008623 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008624 my $String = "";
8625 foreach (@{$ArrRef}) {
8626 $String .= " ".inc_opt($_, $Style);
8627 }
8628 return $String;
8629}
8630
8631sub getIncPaths(@)
8632{
8633 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008634 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008635 if($INC_PATH_AUTODETECT{$Version})
8636 { # auto-detecting dependencies
8637 my %Includes = ();
8638 foreach my $HPath (@HeaderPaths)
8639 {
8640 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8641 {
8642 if($Skip_Include_Paths{$Version}{$Dir}) {
8643 next;
8644 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008645 if($SystemRoot)
8646 {
8647 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8648 next;
8649 }
8650 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008651 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008652 }
8653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008654 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008655 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008656 }
8657 }
8658 else
8659 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008660 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 }
8662 return \@IncPaths;
8663}
8664
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008665sub push_U($@)
8666{ # push unique
8667 if(my $Array = shift @_)
8668 {
8669 if(@_)
8670 {
8671 my %Exist = map {$_=>1} @{$Array};
8672 foreach my $Elem (@_)
8673 {
8674 if(not defined $Exist{$Elem})
8675 {
8676 push(@{$Array}, $Elem);
8677 $Exist{$Elem} = 1;
8678 }
8679 }
8680 }
8681 }
8682}
8683
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008684sub callPreprocessor($$$)
8685{
8686 my ($Path, $Inc, $LibVersion) = @_;
8687 return "" if(not $Path or not -f $Path);
8688 my $IncludeString=$Inc;
8689 if(not $Inc) {
8690 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8691 }
8692 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008693 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008694 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008695 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008696}
8697
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008698sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008699{ # native "find" is much faster than File::Find (~6x)
8700 # also the File::Find doesn't support --maxdepth N option
8701 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008702 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008703 return () if(not $Path or not -e $Path);
8704 if($OSgroup eq "windows")
8705 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008706 $Path = get_abs_path($Path);
8707 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008708 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008709 if($MaxDepth!=1) {
8710 $Cmd .= " /S";
8711 }
8712 if($Type eq "d") {
8713 $Cmd .= " /AD";
8714 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008715 elsif($Type eq "f") {
8716 $Cmd .= " /A-D";
8717 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008718 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008719 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008720 {
8721 if(not $UseRegex)
8722 { # FIXME: how to search file names in MS shell?
8723 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008724 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008725 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008726 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008727 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008728 }
8729 my @AbsPaths = ();
8730 foreach my $File (@Files)
8731 {
8732 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008733 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008734 }
8735 if($Type eq "f" and not -f $File)
8736 { # skip dirs
8737 next;
8738 }
8739 push(@AbsPaths, path_format($File, $OSgroup));
8740 }
8741 if($Type eq "d") {
8742 push(@AbsPaths, $Path);
8743 }
8744 return @AbsPaths;
8745 }
8746 else
8747 {
8748 my $FindCmd = get_CmdPath("find");
8749 if(not $FindCmd) {
8750 exitStatus("Not_Found", "can't find a \"find\" command");
8751 }
8752 $Path = get_abs_path($Path);
8753 if(-d $Path and -l $Path
8754 and $Path!~/\/\Z/)
8755 { # for directories that are symlinks
8756 $Path.="/";
8757 }
8758 my $Cmd = $FindCmd." \"$Path\"";
8759 if($MaxDepth) {
8760 $Cmd .= " -maxdepth $MaxDepth";
8761 }
8762 if($Type) {
8763 $Cmd .= " -type $Type";
8764 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008765 if($Name and not $UseRegex)
8766 { # wildcards
8767 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008768 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008769 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008770 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008771 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8772 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008773 my @Files = split(/\n/, $Res);
8774 if($Name and $UseRegex)
8775 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008776 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008777 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008778 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008779 }
8780}
8781
8782sub unpackDump($)
8783{
8784 my $Path = $_[0];
8785 return "" if(not $Path or not -e $Path);
8786 $Path = get_abs_path($Path);
8787 $Path = path_format($Path, $OSgroup);
8788 my ($Dir, $FileName) = separate_path($Path);
8789 my $UnpackDir = $TMP_DIR."/unpack";
8790 rmtree($UnpackDir);
8791 mkpath($UnpackDir);
8792 if($FileName=~s/\Q.zip\E\Z//g)
8793 { # *.zip
8794 my $UnzipCmd = get_CmdPath("unzip");
8795 if(not $UnzipCmd) {
8796 exitStatus("Not_Found", "can't find \"unzip\" command");
8797 }
8798 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008799 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008801 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008802 }
8803 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008804 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008805 if(not @Contents) {
8806 exitStatus("Error", "can't extract \'$Path\'");
8807 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008808 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008809 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008810 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008812 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 if($OSgroup eq "windows")
8814 { # -xvzf option is not implemented in tar.exe (2003)
8815 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8816 my $TarCmd = get_CmdPath("tar");
8817 if(not $TarCmd) {
8818 exitStatus("Not_Found", "can't find \"tar\" command");
8819 }
8820 my $GzipCmd = get_CmdPath("gzip");
8821 if(not $GzipCmd) {
8822 exitStatus("Not_Found", "can't find \"gzip\" command");
8823 }
8824 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008825 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008826 if($?) {
8827 exitStatus("Error", "can't extract \'$Path\'");
8828 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008829 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008830 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008831 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 }
8833 chdir($ORIG_DIR);
8834 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008835 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008836 if(not @Contents) {
8837 exitStatus("Error", "can't extract \'$Path\'");
8838 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008839 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008840 }
8841 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008842 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008843 my $TarCmd = get_CmdPath("tar");
8844 if(not $TarCmd) {
8845 exitStatus("Not_Found", "can't find \"tar\" command");
8846 }
8847 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008848 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008849 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008850 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008851 }
8852 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008853 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008854 if(not @Contents) {
8855 exitStatus("Error", "can't extract \'$Path\'");
8856 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008857 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008858 }
8859 }
8860}
8861
8862sub createArchive($$)
8863{
8864 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008865 if(not $To) {
8866 $To = ".";
8867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008868 if(not $Path or not -e $Path
8869 or not -d $To) {
8870 return "";
8871 }
8872 my ($From, $Name) = separate_path($Path);
8873 if($OSgroup eq "windows")
8874 { # *.zip
8875 my $ZipCmd = get_CmdPath("zip");
8876 if(not $ZipCmd) {
8877 exitStatus("Not_Found", "can't find \"zip\"");
8878 }
8879 my $Pkg = $To."/".$Name.".zip";
8880 unlink($Pkg);
8881 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008882 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008883 if($?)
8884 { # cannot allocate memory (or other problems with "zip")
8885 unlink($Path);
8886 exitStatus("Error", "can't pack the ABI dump: ".$!);
8887 }
8888 chdir($ORIG_DIR);
8889 unlink($Path);
8890 return $Pkg;
8891 }
8892 else
8893 { # *.tar.gz
8894 my $TarCmd = get_CmdPath("tar");
8895 if(not $TarCmd) {
8896 exitStatus("Not_Found", "can't find \"tar\"");
8897 }
8898 my $GzipCmd = get_CmdPath("gzip");
8899 if(not $GzipCmd) {
8900 exitStatus("Not_Found", "can't find \"gzip\"");
8901 }
8902 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8903 unlink($Pkg);
8904 chdir($From);
8905 system($TarCmd, "-czf", $Pkg, $Name);
8906 if($?)
8907 { # cannot allocate memory (or other problems with "tar")
8908 unlink($Path);
8909 exitStatus("Error", "can't pack the ABI dump: ".$!);
8910 }
8911 chdir($ORIG_DIR);
8912 unlink($Path);
8913 return $To."/".$Name.".tar.gz";
8914 }
8915}
8916
8917sub is_header_file($)
8918{
8919 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8920 return $_[0];
8921 }
8922 return 0;
8923}
8924
8925sub is_not_header($)
8926{
8927 if($_[0]=~/\.\w+\Z/
8928 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8929 return 1;
8930 }
8931 return 0;
8932}
8933
8934sub is_header($$$)
8935{
8936 my ($Header, $UserDefined, $LibVersion) = @_;
8937 return 0 if(-d $Header);
8938 if(-f $Header) {
8939 $Header = get_abs_path($Header);
8940 }
8941 else
8942 {
8943 if(is_abs($Header))
8944 { # incorrect absolute path
8945 return 0;
8946 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008947 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008948 $Header = $HPath;
8949 }
8950 else
8951 { # can't find header
8952 return 0;
8953 }
8954 }
8955 if($Header=~/\.\w+\Z/)
8956 { # have an extension
8957 return is_header_file($Header);
8958 }
8959 else
8960 {
8961 if($UserDefined==2)
8962 { # specified on the command line
8963 if(cmd_file($Header)!~/HTML|XML/i) {
8964 return $Header;
8965 }
8966 }
8967 elsif($UserDefined)
8968 { # specified in the XML-descriptor
8969 # header file without an extension
8970 return $Header;
8971 }
8972 else
8973 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008974 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008975 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008976 { # !~/HTML|XML|shared|dynamic/i
8977 return $Header;
8978 }
8979 }
8980 }
8981 return 0;
8982}
8983
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008984sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008985{
8986 my $LibVersion = $_[0];
8987 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8988 {
8989 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008990 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008991
8992 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8993 detect_recursive_includes($RegHeader, $LibVersion);
8994 }
8995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008996 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8997 {
8998 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008999
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009000 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009001 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9002 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009003 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009004 }
9005 }
9006 }
9007}
9008
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009009sub familiarDirs($$)
9010{
9011 my ($D1, $D2) = @_;
9012 if($D1 eq $D2) {
9013 return 1;
9014 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009015
9016 my $U1 = index($D1, "/usr/");
9017 my $U2 = index($D2, "/usr/");
9018
9019 if($U1==0 and $U2!=0) {
9020 return 0;
9021 }
9022
9023 if($U2==0 and $U1!=0) {
9024 return 0;
9025 }
9026
9027 if(index($D2, $D1."/")==0) {
9028 return 1;
9029 }
9030
9031 # /usr/include/DIR
9032 # /home/user/DIR
9033
9034 my $DL = get_depth($D1);
9035
9036 my @Dirs1 = ($D1);
9037 while($DL - get_depth($D1)<=2
9038 and get_depth($D1)>=4
9039 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9040 push(@Dirs1, $D1);
9041 }
9042
9043 my @Dirs2 = ($D2);
9044 while(get_depth($D2)>=4
9045 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9046 push(@Dirs2, $D2);
9047 }
9048
9049 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009050 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009051 foreach my $P2 (@Dirs2)
9052 {
9053
9054 if($P1 eq $P2) {
9055 return 1;
9056 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009057 }
9058 }
9059 return 0;
9060}
9061
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009062sub readHeaders($)
9063{
9064 $Version = $_[0];
9065 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9066 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009067 if($Debug)
9068 { # debug mode
9069 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009070 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009071 }
9072 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009073}
9074
9075sub prepareTypes($)
9076{
9077 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009078 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009079 { # support for old ABI dumps
9080 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009081 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009082 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009083 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9084 if($TName=~/\A(\w+)::(\w+)/) {
9085 my ($P1, $P2) = ($1, $2);
9086 if($P1 eq $P2) {
9087 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009089 else {
9090 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009092 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009093 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009094 }
9095 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009096 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009097 { # support for old ABI dumps
9098 # V < 2.5: array size == "number of elements"
9099 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009100 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009101 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009102 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009103 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009104 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009105 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009106 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009107 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009108 $Size *= $Base{"Size"};
9109 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009110 }
9111 else
9112 { # array[] is a pointer
9113 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009114 }
9115 }
9116 }
9117 }
9118 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009119 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009120 { # support for old ABI dumps
9121 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009122 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009123 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009124 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009125 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009127 my %Type = get_Type($TypeId, $LibVersion);
9128 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9129 my %Type2 = get_Type($TypeId_2, $V2);
9130 if($Type{"Size"} ne $Type2{"Size"}) {
9131 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009132 }
9133 }
9134 }
9135 }
9136}
9137
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009138sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009139{
9140 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009141
9142 if(not keys(%{$SymbolInfo{$LibVersion}}))
9143 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009144 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009145 {
9146 if($CheckHeadersOnly) {
9147 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9148 }
9149 else {
9150 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9151 }
9152 }
9153 }
9154
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009155 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009156 if(not checkDump(1, "2.10")
9157 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009158 { # different formats
9159 $Remangle = 1;
9160 }
9161 if($CheckHeadersOnly)
9162 { # different languages
9163 if($UserLang)
9164 { # --lang=LANG for both versions
9165 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9166 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9167 {
9168 if($UserLang eq "C++")
9169 { # remangle symbols
9170 $Remangle = 1;
9171 }
9172 elsif($UserLang eq "C")
9173 { # remove mangling
9174 $Remangle = -1;
9175 }
9176 }
9177 }
9178 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009179
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009180 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009182 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009183 { # support for old ABI dumps
9184 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9185 {
9186 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9187 {
9188 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9189 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009190 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009191 if(defined $DVal and $DVal ne "")
9192 {
9193 if($TName eq "char") {
9194 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9195 }
9196 elsif($TName eq "bool") {
9197 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9198 }
9199 }
9200 }
9201 }
9202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009203 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009204 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009205 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9206 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009207 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009208 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9209 # + support for old ABI dumps
9210 next;
9211 }
9212 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009213 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009214 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009215 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009216 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009217
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009218 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009219 if(not checkDump(1, "2.12")
9220 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009221 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009222 if($ShortName eq "operator>>")
9223 {
9224 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9225 { # corrected mangling of operator>>
9226 $SRemangle = 1;
9227 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009229 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9230 {
9231 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9232 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9233 { # corrected mangling of const global data
9234 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9235 # and incorrectly mangled by old ACC versions
9236 $SRemangle = 1;
9237 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009238 }
9239 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009240 if(not $CheckHeadersOnly)
9241 { # support for old ABI dumps
9242 if(not checkDump(1, "2.17")
9243 or not checkDump(2, "2.17"))
9244 {
9245 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9246 {
9247 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9248 {
9249 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9250 {
9251 $MnglName = $ShortName;
9252 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9253 }
9254 }
9255 }
9256 }
9257 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009258 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009259 { # support for old ABI dumps: some symbols are not mangled in old dumps
9260 # mangle both sets of symbols (old and new)
9261 # NOTE: remangling all symbols by the same mangler
9262 if($MnglName=~/\A_ZN(V|)K/)
9263 { # mangling may be incorrect on old ABI dumps
9264 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009265 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009266 }
9267 if($MnglName=~/\A_ZN(K|)V/)
9268 { # mangling may be incorrect on old ABI dumps
9269 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009270 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009271 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009272 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9273 or (not $ClassID and $CheckHeadersOnly)
9274 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9275 { # support for old ABI dumps, GCC >= 4.0
9276 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009277 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009278 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009279 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009280 $MangledNames{$LibVersion}{$MnglName} = 1;
9281 }
9282 }
9283 }
9284 elsif($Remangle==-1)
9285 { # remove mangling
9286 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009287 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 if(not $MnglName) {
9290 next;
9291 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009292
9293 # NOTE: duplicated entries in the ABI Dump
9294 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9295 {
9296 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9297 {
9298 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9299 {
9300 next;
9301 }
9302 }
9303 }
9304
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009305 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9306 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009307 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009309 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009310 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009311 { # support for old dumps
9312 # add "Volatile" attribute
9313 if($MnglName=~/_Z(K|)V/) {
9314 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9315 }
9316 }
9317 # symbol and its symlink have same signatures
9318 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009319 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009320 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009321
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009322 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9323 {
9324 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009325
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009326 if($SymVer{$LibVersion}{$Alias}) {
9327 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9328 }
9329 }
9330
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009331 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009332 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 }
9334 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9335 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9336 }
9337 if($ExtendedCheck)
9338 { # --ext option
9339 addExtension($LibVersion);
9340 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009341
9342 # clean memory
9343 delete($SymbolInfo{$LibVersion});
9344
9345 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 { # detect allocable classes with public exported constructors
9347 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009348 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009349 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009350 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009351 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009352 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9353 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009354 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009355 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009356 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009357 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009358 $AllocableClass{$LibVersion}{$ClassName} = 1;
9359 }
9360 }
9361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009362 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009363 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009364 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009365 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009366 if($CheckHeadersOnly)
9367 {
9368 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9369 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9370 { # all symbols except non-virtual inline
9371 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9372 }
9373 }
9374 else {
9375 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 }
9377 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009378 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009379 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009380 }
9381 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009382 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009383 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009384 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009386 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009387 if(defined $Base{"Type"}
9388 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009389 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009390 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009391 if($Name=~/<([^<>\s]+)>/)
9392 {
9393 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9394 $ReturnedClass{$LibVersion}{$Tid} = 1;
9395 }
9396 }
9397 else {
9398 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9399 }
9400 }
9401 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009402 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009403 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009404 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009405 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009407 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009409 if($Base{"Type"}=~/Struct|Class/)
9410 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009411 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009412 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9413 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009414 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 }
9417 }
9418 }
9419 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009420
9421 # mapping {short name => symbols}
9422 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009423 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009424 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009425 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009426 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009427 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009428 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009430 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9431 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009432 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009433 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009434 }
9435 }
9436 }
9437 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009438
9439 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009440 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009442 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009444 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9445 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009447 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009448 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009449 $ClassNames{$LibVersion}{$TName} = 1;
9450 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009452 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9453 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009454 }
9455 }
9456 }
9457 }
9458 }
9459}
9460
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009461sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009462{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009463 my ($Tid, $LibVersion) = @_;
9464 if(not $Tid) {
9465 return $Tid;
9466 }
9467
9468 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9469 {
9470 if($TName_Tid{$LibVersion}{$Name}) {
9471 return $TName_Tid{$LibVersion}{$Name};
9472 }
9473 }
9474
9475 return $Tid;
9476}
9477
9478sub register_SymbolUsage($$$)
9479{
9480 my ($InfoId, $UsedType, $LibVersion) = @_;
9481
9482 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9483 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9484 {
9485 register_TypeUsage($RTid, $UsedType, $LibVersion);
9486 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9487 }
9488 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9489 {
9490 register_TypeUsage($FCid, $UsedType, $LibVersion);
9491 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9492
9493 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9494 { # register "this" pointer
9495 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9496 }
9497 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9498 { # register "this" pointer (const method)
9499 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9500 }
9501 }
9502 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9503 {
9504 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9505 {
9506 register_TypeUsage($PTid, $UsedType, $LibVersion);
9507 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9508 }
9509 }
9510 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9511 {
9512 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9513 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9514 register_TypeUsage($TTid, $UsedType, $LibVersion);
9515 }
9516 }
9517}
9518
9519sub register_TypeUsage($$$)
9520{
9521 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009522 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009523 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009524 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009525 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009526 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009527 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009528 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009529
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009530 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009531 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009532 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009533 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009534 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009535 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9536 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9537 }
9538 }
9539
9540 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9541 {
9542 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009543 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009544 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009545 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9546 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009547 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009548 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9549 {
9550 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9551 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009552 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009553 }
9554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009555 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009556 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009557 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009558 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9559 {
9560 register_TypeUsage($MTid, $UsedType, $LibVersion);
9561 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009562 }
9563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009564 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009565 or $TInfo{"Type"} eq "MethodPtr"
9566 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009567 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009568 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009569 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009570 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009571 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009572 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009573 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9574 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009575 }
9576 }
9577 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009578 if($TInfo{"Type"} eq "FieldPtr")
9579 {
9580 if(my $RTid = $TInfo{"Return"}) {
9581 register_TypeUsage($RTid, $UsedType, $LibVersion);
9582 }
9583 if(my $CTid = $TInfo{"Class"}) {
9584 register_TypeUsage($CTid, $UsedType, $LibVersion);
9585 }
9586 }
9587 if($TInfo{"Type"} eq "MethodPtr")
9588 {
9589 if(my $CTid = $TInfo{"Class"}) {
9590 register_TypeUsage($CTid, $UsedType, $LibVersion);
9591 }
9592 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009593 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009594 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009595 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009596 $UsedType->{$TypeId} = 1;
9597 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9598 {
9599 register_TypeUsage($BTid, $UsedType, $LibVersion);
9600 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9601 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009602 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009603 else
9604 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9605 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009606 }
9607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009608}
9609
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009610sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009611{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009612 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9613
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009614 if($Level eq "Dump")
9615 {
9616 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9617 { # TODO: check if this symbol is from
9618 # base classes of other target symbols
9619 return 1;
9620 }
9621 }
9622
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009623 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9624 { # stdc++ interfaces
9625 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009626 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009627
9628 my $Target = 0;
9629 if(my $Header = $SInfo->{"Header"}) {
9630 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9631 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009632 if($ExtendedCheck)
9633 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009634 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009635 $Target = 1;
9636 }
9637 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009638 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009639 {
9640 if($Target)
9641 {
9642 if($Level eq "Dump")
9643 { # dumped
9644 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009645 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009646 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009647 return 1;
9648 }
9649 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009650 else {
9651 return 1;
9652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009653 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009654 elsif($Level eq "Source")
9655 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009656 return 1;
9657 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009658 elsif($Level eq "Binary")
9659 { # checked
9660 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9661 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9662 return 1;
9663 }
9664 }
9665 }
9666 }
9667 else
9668 { # library is available
9669 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9670 { # exported symbols
9671 return 1;
9672 }
9673 if($Level eq "Dump")
9674 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009675 if($BinaryOnly)
9676 {
9677 if($SInfo->{"Data"})
9678 {
9679 if($Target) {
9680 return 1;
9681 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009682 }
9683 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009684 else
9685 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009686 if($Target) {
9687 return 1;
9688 }
9689 }
9690 }
9691 elsif($Level eq "Source")
9692 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009693 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009694 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009695 { # skip LOCAL symbols
9696 if($Target) {
9697 return 1;
9698 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009699 }
9700 }
9701 elsif($Level eq "Binary")
9702 { # checked
9703 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9704 {
9705 if($Target) {
9706 return 1;
9707 }
9708 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009709 }
9710 }
9711 return 0;
9712}
9713
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714sub cleanDump($)
9715{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009716 my $LibVersion = $_[0];
9717 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9718 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009719 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9720 {
9721 delete($SymbolInfo{$LibVersion}{$InfoId});
9722 next;
9723 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009724 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009725 if(not $MnglName)
9726 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009727 delete($SymbolInfo{$LibVersion}{$InfoId});
9728 next;
9729 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009730 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009731 if(not $ShortName)
9732 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009733 delete($SymbolInfo{$LibVersion}{$InfoId});
9734 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009735 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009736 if($MnglName eq $ShortName)
9737 { # remove duplicate data
9738 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009739 }
9740 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9741 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9742 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009743 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9744 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9745 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009746 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009748 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009749 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009750 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9751 {
9752 delete($TypeInfo{$LibVersion}{$Tid});
9753 next;
9754 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009755 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009756 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009757 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009758 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9759 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9760 }
9761 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009762 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9763 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9764 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009765 }
9766}
9767
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009768sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009769{
9770 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009771
9772 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9773 {
9774 if(defined $TypeInfo{$LibVersion}{$Dupl})
9775 {
9776 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9777 { # duplicate
9778 return 0;
9779 }
9780 }
9781 }
9782
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009783 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9784
9785 if(isBuiltIn($THeader)) {
9786 return 0;
9787 }
9788
9789 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9790 return 0;
9791 }
9792
9793 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9794 return 0;
9795 }
9796
9797 if(selfTypedef($Tid, $LibVersion)) {
9798 return 0;
9799 }
9800
9801 if(not isTargetType($Tid, $LibVersion)) {
9802 return 0;
9803 }
9804
9805 return 0;
9806}
9807
9808sub isTargetType($$)
9809{
9810 my ($Tid, $LibVersion) = @_;
9811
9812 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9813 { # derived
9814 return 1;
9815 }
9816
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009817 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009818 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009819 if(not is_target_header($THeader, $LibVersion))
9820 { # from target headers
9821 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009822 }
9823 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009824 else
9825 { # NOTE: if type is defined in source
9826 if($UsedDump{$LibVersion}{"Public"})
9827 {
9828 if(isPrivateABI($Tid, $LibVersion)) {
9829 return 0;
9830 }
9831 else {
9832 return 1;
9833 }
9834 }
9835 else {
9836 return 0;
9837 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009838 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009839
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009840 if($SkipInternalTypes)
9841 {
9842 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9843 {
9844 return 0;
9845 }
9846 }
9847
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009848 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009849}
9850
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009851sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009852{ # remove unused data types from the ABI dump
9853 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009854
9855 my %UsedType = ();
9856
9857 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009858 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009859 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009860 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009861 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009862 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009863 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009864 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009865 next;
9866 }
9867
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009868 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009869 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009870 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009871 {
9872 my %Tree = ();
9873 register_TypeUsage($Tid, \%Tree, $LibVersion);
9874
9875 my $Tmpl = 0;
9876 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9877 {
9878 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9879 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9880 {
9881 $Tmpl = 1;
9882 last;
9883 }
9884 }
9885 if(not $Tmpl)
9886 {
9887 foreach (keys(%Tree)) {
9888 $UsedType{$_} = 1;
9889 }
9890 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009891 }
9892 }
9893 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009894
9895 my %Delete = ();
9896
9897 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009898 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009899 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009900 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009901 next;
9902 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009903
9904 if($Kind eq "Extra")
9905 {
9906 my %Tree = ();
9907 register_TypeUsage($Tid, \%Tree, $LibVersion);
9908
9909 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9910 {
9911 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9912 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9913 {
9914 $Delete{$Tid} = 1;
9915 last;
9916 }
9917 }
9918 }
9919 else
9920 {
9921 # remove type
9922 delete($TypeInfo{$LibVersion}{$Tid});
9923 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009924 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009925
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009926 if($Kind eq "Extra")
9927 { # remove duplicates
9928 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9929 {
9930 if($UsedType{$Tid})
9931 { # All & Extended
9932 next;
9933 }
9934
9935 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9936
9937 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9938 delete($TypeInfo{$LibVersion}{$Tid});
9939 }
9940 }
9941 }
9942
9943 foreach my $Tid (keys(%Delete))
9944 {
9945 delete($TypeInfo{$LibVersion}{$Tid});
9946 }
9947}
9948
9949sub check_Completeness($$)
9950{
9951 my ($Info, $LibVersion) = @_;
9952
9953 # data types
9954 if(defined $Info->{"Memb"})
9955 {
9956 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9957 {
9958 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9959 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9960 }
9961 }
9962 }
9963 if(defined $Info->{"Base"})
9964 {
9965 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9966 check_TypeInfo($Bid, $LibVersion);
9967 }
9968 }
9969 if(defined $Info->{"BaseType"}) {
9970 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9971 }
9972 if(defined $Info->{"TParam"})
9973 {
9974 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9975 {
9976 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9977 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9978 next;
9979 }
9980 if($TName eq "_BoolType") {
9981 next;
9982 }
9983 if($TName=~/\Asizeof\(/) {
9984 next;
9985 }
9986 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9987 check_TypeInfo($Tid, $LibVersion);
9988 }
9989 else
9990 {
9991 if(defined $Debug) {
9992 printMsg("WARNING", "missed type $TName");
9993 }
9994 }
9995 }
9996 }
9997
9998 # symbols
9999 if(defined $Info->{"Param"})
10000 {
10001 foreach my $Pos (keys(%{$Info->{"Param"}}))
10002 {
10003 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10004 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10005 }
10006 }
10007 }
10008 if(defined $Info->{"Return"}) {
10009 check_TypeInfo($Info->{"Return"}, $LibVersion);
10010 }
10011 if(defined $Info->{"Class"}) {
10012 check_TypeInfo($Info->{"Class"}, $LibVersion);
10013 }
10014}
10015
10016sub check_TypeInfo($$)
10017{
10018 my ($Tid, $LibVersion) = @_;
10019
10020 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10021 return;
10022 }
10023 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10024
10025 if(defined $TypeInfo{$LibVersion}{$Tid})
10026 {
10027 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10028 printMsg("ERROR", "missed type name ($Tid)");
10029 }
10030 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10031 }
10032 else {
10033 printMsg("ERROR", "missed type id $Tid");
10034 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010035}
10036
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010037sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010038{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010039 my ($TypeId, $LibVersion) = @_;
10040 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010041 if($Type{"Type"} eq "Typedef")
10042 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010043 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010044 if($Base{"Type"}=~/Class|Struct/)
10045 {
10046 if($Type{"Name"} eq $Base{"Name"}) {
10047 return 1;
10048 }
10049 elsif($Type{"Name"}=~/::(\w+)\Z/)
10050 {
10051 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10052 { # QPointer<QWidget>::QPointer
10053 return 1;
10054 }
10055 }
10056 }
10057 }
10058 return 0;
10059}
10060
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010061sub addExtension($)
10062{
10063 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010064 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010065 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010066 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010067 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010068 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10069 $TName=~s/\A(struct|union|class|enum) //;
10070 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010071
10072 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10073 "Header" => "extended.h",
10074 "ShortName" => $Symbol,
10075 "MnglName" => $Symbol,
10076 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10077 );
10078
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010079 $ExtendedSymbols{$Symbol} = 1;
10080 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10081 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010082 }
10083 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010084 $ExtendedSymbols{"external_func_0"} = 1;
10085 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10086 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010087}
10088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010089sub findMethod($$$)
10090{
10091 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010092 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010093 {
10094 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10095 return $VirtMethodInClass;
10096 }
10097 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10098 return $VirtMethodInBaseClasses;
10099 }
10100 }
10101 return "";
10102}
10103
10104sub findMethod_Class($$$)
10105{
10106 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010107 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010108 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10109 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10110 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10111 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10112 { # search for interface with the same parameters suffix (overridden)
10113 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10114 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010115 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10116 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010117 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10118 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010119 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10120 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10121 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10122 return $Candidate;
10123 }
10124 }
10125 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010126 else
10127 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010128 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10129 return $Candidate;
10130 }
10131 }
10132 }
10133 }
10134 return "";
10135}
10136
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010137sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010138{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010139 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010140 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010141 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010142 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10143 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010144 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010145 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010146 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010147 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10148 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010149 { # pure virtual D2-destructors are marked as "virt" in the dump
10150 # virtual D2-destructors are NOT marked as "virt" in the dump
10151 # both destructors are not presented in the v-table
10152 next;
10153 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010154 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010155 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010157 }
10158}
10159
10160sub registerOverriding($)
10161{
10162 my $LibVersion = $_[0];
10163 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010164 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010165 foreach my $ClassName (@Classes)
10166 {
10167 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10168 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010169 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10170 { # pure virtuals
10171 next;
10172 }
10173 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10174 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010175 {
10176 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10177 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10178 { # both overridden virtual methods
10179 # and implemented pure virtual methods
10180 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10181 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10182 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010184 }
10185 }
10186 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10187 delete($VirtualTable{$LibVersion}{$ClassName});
10188 }
10189 }
10190}
10191
10192sub setVirtFuncPositions($)
10193{
10194 my $LibVersion = $_[0];
10195 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10196 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010197 my ($Num, $Rel) = (1, 0);
10198
10199 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010200 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010201 if($UsedDump{$LibVersion}{"DWARF"}) {
10202 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10203 }
10204 else {
10205 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10206 }
10207 foreach my $VirtFunc (@Funcs)
10208 {
10209 if($UsedDump{$LibVersion}{"DWARF"}) {
10210 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10211 }
10212 else {
10213 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10214 }
10215
10216 # set relative positions
10217 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10218 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10219 { # relative position excluding added and removed virtual functions
10220 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10221 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10222 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010224 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010226 }
10227 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010228 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010229 {
10230 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010231 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010232 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010233 }
10234 }
10235}
10236
10237sub get_sub_classes($$$)
10238{
10239 my ($ClassId, $LibVersion, $Recursive) = @_;
10240 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10241 my @Subs = ();
10242 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10243 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010244 if($Recursive)
10245 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010246 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10247 push(@Subs, $SubSubId);
10248 }
10249 }
10250 push(@Subs, $SubId);
10251 }
10252 return @Subs;
10253}
10254
10255sub get_base_classes($$$)
10256{
10257 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010258 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010259 return () if(not defined $ClassType{"Base"});
10260 my @Bases = ();
10261 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10262 keys(%{$ClassType{"Base"}}))
10263 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010264 if($Recursive)
10265 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010266 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10267 push(@Bases, $SubBaseId);
10268 }
10269 }
10270 push(@Bases, $BaseId);
10271 }
10272 return @Bases;
10273}
10274
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010275sub getVTable_Model($$)
10276{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010277 my ($ClassId, $LibVersion) = @_;
10278 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10279 my @Elements = ();
10280 foreach my $BaseId (@Bases, $ClassId)
10281 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010282 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010283 {
10284 if(defined $VirtualTable{$LibVersion}{$BName})
10285 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010286 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10287 if($UsedDump{$LibVersion}{"DWARF"}) {
10288 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10289 }
10290 else {
10291 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10292 }
10293 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010294 push(@Elements, $VFunc);
10295 }
10296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010297 }
10298 }
10299 return @Elements;
10300}
10301
10302sub getVShift($$)
10303{
10304 my ($ClassId, $LibVersion) = @_;
10305 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10306 my $VShift = 0;
10307 foreach my $BaseId (@Bases)
10308 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010309 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010310 {
10311 if(defined $VirtualTable{$LibVersion}{$BName}) {
10312 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010314 }
10315 }
10316 return $VShift;
10317}
10318
10319sub getShift($$)
10320{
10321 my ($ClassId, $LibVersion) = @_;
10322 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10323 my $Shift = 0;
10324 foreach my $BaseId (@Bases)
10325 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010326 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010327 {
10328 if($Size!=1)
10329 { # not empty base class
10330 $Shift+=$Size;
10331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010332 }
10333 }
10334 return $Shift;
10335}
10336
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010337sub getVTable_Size($$)
10338{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010339 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010340 my $Size = 0;
10341 # three approaches
10342 if(not $Size)
10343 { # real size
10344 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10345 $Size = keys(%VTable);
10346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010347 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010348 if(not $Size)
10349 { # shared library symbol size
10350 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10351 $Size /= $WORD_SIZE{$LibVersion};
10352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010354 if(not $Size)
10355 { # model size
10356 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10357 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10358 }
10359 }
10360 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010361}
10362
10363sub isCopyingClass($$)
10364{
10365 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010366 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010367}
10368
10369sub isLeafClass($$)
10370{
10371 my ($ClassId, $LibVersion) = @_;
10372 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10373}
10374
10375sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010376{ # check structured type for public fields
10377 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010378}
10379
10380sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010381{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010382 my ($TypePtr, $Skip, $Start, $End) = @_;
10383 return 0 if(not $TypePtr);
10384 if($End==-1) {
10385 $End = keys(%{$TypePtr->{"Memb"}})-1;
10386 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010387 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010388 {
10389 if($Skip and $Skip->{$MemPos})
10390 { # skip removed/added fields
10391 next;
10392 }
10393 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10394 {
10395 if(isPublic($TypePtr, $MemPos)) {
10396 return ($MemPos+1);
10397 }
10398 }
10399 }
10400 return 0;
10401}
10402
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010403sub isReserved($)
10404{ # reserved fields == private
10405 my $MName = $_[0];
10406 if($MName=~/reserved|padding|f_spare/i) {
10407 return 1;
10408 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010409 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010410 return 1;
10411 }
10412 if($MName=~/(pad\d+)/i) {
10413 return 1;
10414 }
10415 return 0;
10416}
10417
10418sub isPublic($$)
10419{
10420 my ($TypePtr, $FieldPos) = @_;
10421 return 0 if(not $TypePtr);
10422 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10423 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10424 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10425 { # by name in C language
10426 # FIXME: add other methods to detect private members
10427 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10428 if($MName=~/priv|abidata|parent_object/i)
10429 { # C-styled private data
10430 return 0;
10431 }
10432 if(lc($MName) eq "abi")
10433 { # ABI information/reserved field
10434 return 0;
10435 }
10436 if(isReserved($MName))
10437 { # reserved fields
10438 return 0;
10439 }
10440 return 1;
10441 }
10442 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10443 { # by access in C++ language
10444 return 1;
10445 }
10446 return 0;
10447}
10448
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010449sub getVTable_Real($$)
10450{
10451 my ($ClassName, $LibVersion) = @_;
10452 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10453 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010454 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010455 if(defined $Type{"VTable"}) {
10456 return %{$Type{"VTable"}};
10457 }
10458 }
10459 return ();
10460}
10461
10462sub cmpVTables($)
10463{
10464 my $ClassName = $_[0];
10465 my $Res = cmpVTables_Real($ClassName, 1);
10466 if($Res==-1) {
10467 $Res = cmpVTables_Model($ClassName);
10468 }
10469 return $Res;
10470}
10471
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472sub cmpVTables_Model($)
10473{
10474 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010475 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010476 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010477 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010478 return 1;
10479 }
10480 }
10481 return 0;
10482}
10483
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010484sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010485{
10486 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10488 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010489 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 my %VTable_Old = getVTable_Real($ClassName, 1);
10491 my %VTable_New = getVTable_Real($ClassName, 2);
10492 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010493 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010494 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010495 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010496 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10498 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010501 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010502 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010503 my $Entry1 = $VTable_Old{$Offset};
10504 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010506 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010507 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010508 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510 $Entry1 = simpleVEntry($Entry1);
10511 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010512
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010513 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010514 { # NOTE: problem with vtable-dumper
10515 next;
10516 }
10517
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 if($Entry1 ne $Entry2)
10519 { # register as changed
10520 if($Entry1=~/::([^:]+)\Z/)
10521 {
10522 my $M1 = $1;
10523 if($Entry2=~/::([^:]+)\Z/)
10524 {
10525 my $M2 = $1;
10526 if($M1 eq $M2)
10527 { # overridden
10528 next;
10529 }
10530 }
10531 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010532 if(differentDumps("G"))
10533 {
10534 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10535 {
10536 # GCC 4.6.1: -0x00000000000000010
10537 # GCC 4.7.0: -16
10538 next;
10539 }
10540 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010541 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010542 }
10543 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010545}
10546
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010547sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010548{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010549 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010550 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10551 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010552 my $ClassId = $TName_Tid{1}{$ClassName};
10553 if(isPrivateABI($ClassId, 1)) {
10554 next;
10555 }
10556
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010557 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010558 { # already registered
10559 next;
10560 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010561 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010563 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010564 foreach my $Symbol (@Affected)
10565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010566 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010568 "Target"=>$ClassName);
10569 }
10570 }
10571 }
10572}
10573
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010574sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010576 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010577 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010579 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010580 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010581
10582 if(isPrivateABI($ClassId, 1)) {
10583 next;
10584 }
10585
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010586 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010588 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010589 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010590 if($TName_Tid{1}{$ClassName}
10591 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010592 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010593 if(defined $CompleteSignature{1}{$Symbol}
10594 and $CompleteSignature{1}{$Symbol}{"Virt"})
10595 { # override some method in v.1
10596 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010597 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010598 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 }
10600 }
10601 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010602 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010604 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010605 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010606 if($TName_Tid{2}{$ClassName}
10607 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010608 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 if(defined $CompleteSignature{2}{$Symbol}
10610 and $CompleteSignature{2}{$Symbol}{"Virt"})
10611 { # override some method in v.2
10612 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010613 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010614 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 }
10616 }
10617 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010618 if($Level eq "Binary")
10619 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010620 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010621 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10622 { # check replacements, including pure virtual methods
10623 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10624 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010626 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10627 if($AddedPos==$RemovedPos)
10628 {
10629 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10630 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10631 last; # other methods will be reported as "added" or "removed"
10632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010634 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10635 {
10636 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10637 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010638 next;
10639 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010640 my $ProblemType = "Virtual_Replacement";
10641 my @Affected = ($RemovedVFunc);
10642 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10643 { # pure methods
10644 if(not isUsedClass($ClassId, 1, $Level))
10645 { # not a parameter of some exported method
10646 next;
10647 }
10648 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010649
10650 # affected all methods (both virtual and non-virtual ones)
10651 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10652 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010654 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010655 foreach my $AffectedInt (@Affected)
10656 {
10657 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10658 { # affected exported methods only
10659 next;
10660 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010661 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10662 next;
10663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010664 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10665 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010666 "Target"=>get_Signature($AddedVFunc, 2),
10667 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669 }
10670 }
10671 }
10672 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010673 if(not checkDump(1, "2.0")
10674 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010675 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010676 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010677 return;
10678 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010679 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010680 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010681 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010682 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010683
10684 if(isPrivateABI($ClassId_Old, 1)) {
10685 next;
10686 }
10687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 if(not isCreatable($ClassId_Old, 1))
10689 { # skip classes without public constructors (including auto-generated)
10690 # example: class has only a private exported or private inline constructor
10691 next;
10692 }
10693 if($ClassName=~/>/)
10694 { # skip affected template instances
10695 next;
10696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010697 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010698 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010699 if(not $ClassId_New) {
10700 next;
10701 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010702 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010703 if($Class_New{"Type"}!~/Class|Struct/)
10704 { # became typedef
10705 if($Level eq "Binary") {
10706 next;
10707 }
10708 if($Level eq "Source")
10709 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010710 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010711 if($Class_New{"Type"}!~/Class|Struct/) {
10712 next;
10713 }
10714 $ClassId_New = $Class_New{"Tid"};
10715 }
10716 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010717
10718 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10719 { # incomplete info in the ABI dump
10720 next;
10721 }
10722
10723
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010724 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10725 my @Bases_New = sort {$Class_New{"Base"}{$a}{"pos"}<=>$Class_New{"Base"}{$b}{"pos"}} keys(%{$Class_New{"Base"}});
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010726
10727 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10728 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10729
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010730 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010731 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10732 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010733 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10734 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 my $Shift_Old = getShift($ClassId_Old, 1);
10736 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010737 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010738 my ($Added, $Removed) = (0, 0);
10739 my @StableBases_Old = ();
10740 foreach my $BaseId (@Bases_Old)
10741 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010742 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010743 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010744 push(@StableBases_Old, $BaseId);
10745 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010746 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010747 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010748 { # removed base
10749 # excluding namespace::SomeClass to SomeClass renaming
10750 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010751 if($Level eq "Binary")
10752 { # Binary-level
10753 if($Shift_Old ne $Shift_New)
10754 { # affected fields
10755 if(havePubFields(\%Class_Old)) {
10756 $ProblemKind .= "_And_Shift";
10757 }
10758 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10759 $ProblemKind .= "_And_Size";
10760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010761 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010762 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10763 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010764 { # affected v-table
10765 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010766 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010767 }
10768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010769 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010770 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10771 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010772 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10773 {
10774 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10775 if($ProblemKind=~/VTable/) {
10776 $VTableChanged_M{$SubName}=1;
10777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010778 }
10779 }
10780 foreach my $Interface (@Affected)
10781 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010782 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10783 next;
10784 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010785 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010786 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010787 "Target"=>$BaseName,
10788 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10789 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10790 "Shift"=>abs($Shift_New-$Shift_Old) );
10791 }
10792 $Removed+=1;
10793 }
10794 }
10795 my @StableBases_New = ();
10796 foreach my $BaseId (@Bases_New)
10797 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010798 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010799 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010800 push(@StableBases_New, $BaseId);
10801 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010802 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010803 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010804 { # added base
10805 # excluding namespace::SomeClass to SomeClass renaming
10806 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010807 if($Level eq "Binary")
10808 { # Binary-level
10809 if($Shift_Old ne $Shift_New)
10810 { # affected fields
10811 if(havePubFields(\%Class_Old)) {
10812 $ProblemKind .= "_And_Shift";
10813 }
10814 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10815 $ProblemKind .= "_And_Size";
10816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010817 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010818 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10819 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010820 { # affected v-table
10821 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010822 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 }
10824 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010825 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010826 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10827 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010828 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10829 {
10830 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10831 if($ProblemKind=~/VTable/) {
10832 $VTableChanged_M{$SubName}=1;
10833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 }
10835 }
10836 foreach my $Interface (@Affected)
10837 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010838 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10839 next;
10840 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010841 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010842 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010843 "Target"=>$BaseName,
10844 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10845 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10846 "Shift"=>abs($Shift_New-$Shift_Old) );
10847 }
10848 $Added+=1;
10849 }
10850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010851 if($Level eq "Binary")
10852 { # Binary-level
10853 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010854 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10855 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010856 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010857 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010858 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010859 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010860 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10862 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010863 if($NewPos!=$OldPos)
10864 { # changed position of the base class
10865 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010866 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010867 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10868 next;
10869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010870 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10871 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010872 "Target"=>$BaseName,
10873 "Old_Value"=>$OldPos-1,
10874 "New_Value"=>$NewPos-1 );
10875 }
10876 }
10877 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10878 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10879 { # became non-virtual base
10880 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10881 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010882 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10883 next;
10884 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010885 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10886 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010887 "Target"=>$BaseName );
10888 }
10889 }
10890 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10891 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10892 { # became virtual base
10893 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10894 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010895 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10896 next;
10897 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010898 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10899 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010900 "Target"=>$BaseName );
10901 }
10902 }
10903 }
10904 }
10905 # detect size changes in base classes
10906 if($Shift_Old!=$Shift_New)
10907 { # size of allocable class
10908 foreach my $BaseId (@StableBases_Old)
10909 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010910 my %BaseType = get_Type($BaseId, 1);
10911 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010912 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010913 if($Size_Old ne $Size_New
10914 and $Size_Old and $Size_New)
10915 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010916 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010917 if(isCopyingClass($BaseId, 1)) {
10918 $ProblemType = "Size_Of_Copying_Class";
10919 }
10920 elsif($AllocableClass{1}{$BaseType{"Name"}})
10921 {
10922 if($Size_New>$Size_Old)
10923 { # increased size
10924 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010926 else
10927 { # decreased size
10928 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10929 if(not havePubFields(\%Class_Old))
10930 { # affected class has no public members
10931 next;
10932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010934 }
10935 next if(not $ProblemType);
10936 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10937 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010938 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10939 next;
10940 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10942 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010943 "Target"=>$BaseType{"Name"},
10944 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10945 "New_Size"=>$Size_New*$BYTE_SIZE );
10946 }
10947 }
10948 }
10949 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010950 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010951 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010952 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 { # compare virtual tables size in base classes
10954 my $VShift_Old = getVShift($ClassId_Old, 1);
10955 my $VShift_New = getVShift($ClassId_New, 2);
10956 if($VShift_Old ne $VShift_New)
10957 { # changes in the base class or changes in the list of base classes
10958 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10959 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10960 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010961 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010962 foreach my $BaseId (@AllBases_Old)
10963 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010964 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010965 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 { # lost base
10967 next;
10968 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010969 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10970 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010971 if($VSize_Old!=$VSize_New)
10972 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010973 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010974 { # TODO: affected non-virtual methods?
10975 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10977 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010978 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010979 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010980 { # skip interfaces that have not changed the absolute virtual position
10981 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010982 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010983 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10984 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010985 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010986 $VTableChanged_M{$BaseType{"Name"}} = 1;
10987 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010988 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10989 { # the reason of the layout change: added virtual functions
10990 next if($VirtualReplacement{$VirtFunc});
10991 my $ProblemType = "Added_Virtual_Method";
10992 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10993 $ProblemType = "Added_Pure_Virtual_Method";
10994 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010995 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010997 "Target"=>get_Signature($VirtFunc, 2) );
10998 }
10999 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11000 { # the reason of the layout change: removed virtual functions
11001 next if($VirtualReplacement{$VirtFunc});
11002 my $ProblemType = "Removed_Virtual_Method";
11003 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11004 $ProblemType = "Removed_Pure_Virtual_Method";
11005 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011006 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011008 "Target"=>get_Signature($VirtFunc, 1) );
11009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011010 }
11011 }
11012 }
11013 }
11014 }
11015 }
11016 }
11017}
11018
11019sub isCreatable($$)
11020{
11021 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011022 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011023 or isCopyingClass($ClassId, $LibVersion)) {
11024 return 1;
11025 }
11026 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11027 { # Fix for incomplete data: if this class has
11028 # a base class then it should also has a constructor
11029 return 1;
11030 }
11031 if($ReturnedClass{$LibVersion}{$ClassId})
11032 { # returned by some method of this class
11033 # or any other class
11034 return 1;
11035 }
11036 return 0;
11037}
11038
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011039sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011040{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011041 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011042 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11043 { # parameter of some exported method
11044 return 1;
11045 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011046 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11047 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011048 { # method from target class
11049 return 1;
11050 }
11051 return 0;
11052}
11053
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011054sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011055{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011056 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011057 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011058 # - virtual
11059 # - pure-virtual
11060 # - non-virtual
11061 if($CompleteSignature{1}{$Interface}{"Data"})
11062 { # global data is not affected
11063 return;
11064 }
11065 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011066 if(not $Class_Id) {
11067 return;
11068 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011069 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011070 if(cmpVTables_Real($CName, 1)==0)
11071 { # no changes
11072 return;
11073 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011074 $CheckedTypes{$Level}{$CName} = 1;
11075 if($Level eq "Binary")
11076 { # Binary-level
11077 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11078 and not isUsedClass($Class_Id, 1, $Level))
11079 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011080 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011081 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011082 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011083 }
11084 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11085 {
11086 if(defined $VirtualTable{2}{$CName}{$Func}
11087 and defined $CompleteSignature{2}{$Func})
11088 {
11089 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11090 and $CompleteSignature{2}{$Func}{"PureVirt"})
11091 { # became pure virtual
11092 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11093 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011094 "Target"=>get_Signature_M($Func, 1) );
11095 $VTableChanged_M{$CName} = 1;
11096 }
11097 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11098 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11099 { # became non-pure virtual
11100 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11101 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011102 "Target"=>get_Signature_M($Func, 1) );
11103 $VTableChanged_M{$CName} = 1;
11104 }
11105 }
11106 }
11107 if($Level eq "Binary")
11108 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011109 # check virtual table structure
11110 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11111 {
11112 next if($Interface eq $AddedVFunc);
11113 next if($VirtualReplacement{$AddedVFunc});
11114 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11115 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11116 { # pure virtual methods affect all others (virtual and non-virtual)
11117 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011118 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011119 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011120 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011122 elsif(not defined $VirtualTable{1}{$CName}
11123 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011125 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011126 { # became polymorphous class, added v-table pointer
11127 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011128 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011130 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 }
11132 else
11133 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011134 my $VSize_Old = getVTable_Size($CName, 1);
11135 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011136 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 if(isCopyingClass($Class_Id, 1))
11138 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11139 my $ProblemType = "Added_Virtual_Method";
11140 if(isLeafClass($Class_Id, 1)) {
11141 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11142 }
11143 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11144 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011148 else
11149 {
11150 my $ProblemType = "Added_Virtual_Method";
11151 if(isLeafClass($Class_Id, 1)) {
11152 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11153 }
11154 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11155 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011156 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011157 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011159 }
11160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11162 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011163 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011164 if(defined $VirtualTable{1}{$CName}
11165 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011166 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011167 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11168 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011169
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011170 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011171 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011172 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11173 foreach my $ASymbol (@Affected)
11174 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011175 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11176 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011177 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011178 next;
11179 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011180 }
11181 $CheckedSymbols{$Level}{$ASymbol} = 1;
11182 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11183 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011184 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011185 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011188 }
11189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011190 else {
11191 # safe
11192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11195 {
11196 next if($VirtualReplacement{$RemovedVFunc});
11197 if($RemovedVFunc eq $Interface
11198 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11199 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011200 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011201 next;
11202 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011203 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011204 { # became non-polymorphous class, removed v-table pointer
11205 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11206 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011208 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011209 }
11210 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11211 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11212 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011213 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011214 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011215 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11216 next;
11217 }
11218 my $VPos_New = -1;
11219 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011220 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011221 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11222 }
11223 else
11224 {
11225 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 next;
11227 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011228 }
11229 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11230 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11231 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11232 {
11233 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11234 foreach my $ASymbol (@Affected)
11235 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011236 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11237 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011238 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011239 next;
11240 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011241 }
11242 my $ProblemType = "Removed_Virtual_Method";
11243 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11244 $ProblemType = "Removed_Pure_Virtual_Method";
11245 }
11246 $CheckedSymbols{$Level}{$ASymbol} = 1;
11247 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11248 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011249 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011250 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011252 }
11253 }
11254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011255 }
11256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011257 else
11258 { # Source-level
11259 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011261 next if($Interface eq $AddedVFunc);
11262 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011263 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011264 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11265 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011266 "Target"=>get_Signature($AddedVFunc, 2) );
11267 }
11268 }
11269 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11270 {
11271 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11272 {
11273 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11274 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 }
11277 }
11278 }
11279}
11280
11281sub find_MemberPair_Pos_byName($$)
11282{
11283 my ($Member_Name, $Pair_Type) = @_;
11284 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11285 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11286 {
11287 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11288 {
11289 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11290 $Name=~s/\A[_]+|[_]+\Z//g;
11291 if($Name eq $Member_Name) {
11292 return $MemberPair_Pos;
11293 }
11294 }
11295 }
11296 return "lost";
11297}
11298
11299sub find_MemberPair_Pos_byVal($$)
11300{
11301 my ($Member_Value, $Pair_Type) = @_;
11302 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11303 {
11304 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11305 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11306 return $MemberPair_Pos;
11307 }
11308 }
11309 return "lost";
11310}
11311
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011312sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011313{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011314 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011315 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011316 if( $_->{"T1"} eq $_[0]
11317 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011318 {
11319 return 1;
11320 }
11321 }
11322 return 0;
11323}
11324
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011325sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011326{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011327 my %IDs = (
11328 "T1" => $_[0],
11329 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011330 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011331 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011332}
11333
11334sub isRenamed($$$$$)
11335{
11336 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11337 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11338 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011339 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011340 if(not defined $Type2->{"Memb"}{$MemPos}) {
11341 return "";
11342 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011343 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011344 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011345
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011346 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11347 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011348 if($MemberPair_Pos_Rev eq "lost")
11349 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011350 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11351 { # base type match
11352 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011353 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011354 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11355 { # exact type match
11356 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011358 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11359 { # size match
11360 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011361 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011362 if(isReserved($Pair_Name))
11363 { # reserved fields
11364 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 }
11366 }
11367 return "";
11368}
11369
11370sub isLastElem($$)
11371{
11372 my ($Pos, $TypeRef) = @_;
11373 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11374 if($Name=~/last|count|max|total/i)
11375 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11376 return 1;
11377 }
11378 elsif($Name=~/END|NLIMITS\Z/)
11379 { # __RLIMIT_NLIMITS
11380 return 1;
11381 }
11382 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11383 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11384 { # NImageFormats, NColorRoles
11385 return 1;
11386 }
11387 return 0;
11388}
11389
11390sub nonComparable($$)
11391{
11392 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011393
11394 my $N1 = $T1->{"Name"};
11395 my $N2 = $T2->{"Name"};
11396
11397 $N1=~s/\A(struct|union|enum) //;
11398 $N2=~s/\A(struct|union|enum) //;
11399
11400 if($N1 ne $N2
11401 and not isAnon($N1)
11402 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011403 { # different names
11404 if($T1->{"Type"} ne "Pointer"
11405 or $T2->{"Type"} ne "Pointer")
11406 { # compare base types
11407 return 1;
11408 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011409 if($N1!~/\Avoid\s*\*/
11410 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011411 {
11412 return 1;
11413 }
11414 }
11415 elsif($T1->{"Type"} ne $T2->{"Type"})
11416 { # different types
11417 if($T1->{"Type"} eq "Class"
11418 and $T2->{"Type"} eq "Struct")
11419 { # "class" to "struct"
11420 return 0;
11421 }
11422 elsif($T2->{"Type"} eq "Class"
11423 and $T1->{"Type"} eq "Struct")
11424 { # "struct" to "class"
11425 return 0;
11426 }
11427 else
11428 { # "class" to "enum"
11429 # "union" to "class"
11430 # ...
11431 return 1;
11432 }
11433 }
11434 return 0;
11435}
11436
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011437sub isOpaque($)
11438{
11439 my $T = $_[0];
11440 if(not defined $T->{"Memb"})
11441 {
11442 return 1;
11443 }
11444 return 0;
11445}
11446
11447sub removeVPtr($)
11448{ # support for old ABI dumps
11449 my $TPtr = $_[0];
11450 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11451 if($#Pos>=1)
11452 {
11453 foreach my $Pos (0 .. $#Pos-1)
11454 {
11455 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11456 }
11457 delete($TPtr->{"Memb"}{$#Pos});
11458 }
11459}
11460
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011461sub isPrivateABI($$)
11462{
11463 my ($TypeId, $LibVersion) = @_;
11464
11465 if($CheckPrivateABI) {
11466 return 0;
11467 }
11468
11469 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11470 return 1;
11471 }
11472
11473 return 0;
11474}
11475
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011476sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011477{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011478 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011479 return {} if(not $Type1_Id or not $Type2_Id);
11480
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011481 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011482 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011483 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011484 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011485
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011486 my %Type1 = get_Type($Type1_Id, 1);
11487 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011488 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011489 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011490 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011491
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011492 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11493 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011494
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011495 if(defined $UsedDump{1}{"DWARF"})
11496 {
11497 if($Type1_Pure{"Name"} eq "__unknown__"
11498 or $Type2_Pure{"Name"} eq "__unknown__")
11499 { # Error ABI dump
11500 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11501 }
11502 }
11503
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011504 if(isPrivateABI($Type1_Id, 1)) {
11505 return {};
11506 }
11507
11508 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11509 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11510
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011511 my %SubProblems = ();
11512
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011513 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11514 {
11515 if($Type1_Pure{"Type"}=~/Struct|Union/
11516 and $Type2_Pure{"Type"}=~/Struct|Union/)
11517 {
11518 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11519 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011520 if(not defined $UsedDump{1}{"DWARF"}
11521 and not defined $UsedDump{2}{"DWARF"})
11522 {
11523 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11524 "Target"=>$Type1_Pure{"Name"},
11525 "Type_Name"=>$Type1_Pure{"Name"} );
11526 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011527
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011528 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011529 }
11530 }
11531 }
11532
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011533 if(not $Type1_Pure{"Size"}
11534 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011535 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011536 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11537 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11538 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011539 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011540 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011541 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011542 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011543 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011544 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011545 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011546 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11547 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11548 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011549
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011550 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11551 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011552 }
11553
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011554 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11555 { # support for old ABI dumps
11556 # _vptr field added in 3.0
11557 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11558 {
11559 if(defined $Type2_Pure{"Memb"}
11560 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11561 {
11562 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11563 delete($Type2_Pure{"Memb"}{0});
11564 }
11565 else {
11566 removeVPtr(\%Type2_Pure);
11567 }
11568 }
11569 }
11570 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11571 {
11572 if(defined $Type1_Pure{"Memb"}
11573 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11574 {
11575 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11576 delete($Type1_Pure{"Memb"}{0});
11577 }
11578 else {
11579 removeVPtr(\%Type1_Pure);
11580 }
11581 }
11582 }
11583 }
11584
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011585 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11586 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011587
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011588 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011589 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11590 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011591 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011592 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11593 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011594 if($Base_1{"Name"} ne $Base_2{"Name"})
11595 {
11596 if(differentDumps("G")
11597 or differentDumps("V"))
11598 { # different GCC versions or different dumps
11599 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11600 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11601 # std::__va_list and __va_list
11602 $Base_1{"Name"}=~s/\A(\w+::)+//;
11603 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011604 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11605 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011607 }
11608 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11609 and $Base_1{"Name"} ne $Base_2{"Name"})
11610 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011611 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011612 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011613 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011614 {
11615 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11616 "Target"=>$Typedef_1{"Name"},
11617 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011618 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11619 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11620 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011621 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11622 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011623
11624 if(defined $UsedDump{1}{"DWARF"})
11625 {
11626 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11627 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11628 { # Error ABI dump
11629 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11630 }
11631 }
11632
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011633 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011634 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011635 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11636 {
11637 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11638 "Target"=>$Typedef_1{"Name"},
11639 "Type_Name"=>$Typedef_1{"Name"},
11640 "Old_Value"=>$Base_1{"Name"},
11641 "New_Value"=>$Base_2{"Name"} );
11642 }
11643 else
11644 {
11645 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11646 "Target"=>$Typedef_1{"Name"},
11647 "Type_Name"=>$Typedef_1{"Name"},
11648 "Old_Value"=>$Base_1{"Name"},
11649 "New_Value"=>$Base_2{"Name"} );
11650 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011652 }
11653 }
11654 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11655 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011656 my $TT1 = $Type1_Pure{"Type"};
11657 my $TT2 = $Type2_Pure{"Type"};
11658
11659 if($TT1 ne $TT2
11660 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011661 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011662 my $Short1 = $Type1_Pure{"Name"};
11663 my $Short2 = $Type2_Pure{"Name"};
11664
11665 $Short1=~s/\A\Q$TT1\E //ig;
11666 $Short2=~s/\A\Q$TT2\E //ig;
11667
11668 if($Short1 eq $Short2)
11669 {
11670 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11671 "Target"=>$Type1_Pure{"Name"},
11672 "Type_Name"=>$Type1_Pure{"Name"},
11673 "Old_Value"=>lc($Type1_Pure{"Type"}),
11674 "New_Value"=>lc($Type2_Pure{"Type"}) );
11675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011676 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011677 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011678 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011679 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011680 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11681 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11682 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11683 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011684 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011685 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011686 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011687 {
11688 my $ProblemKind = "DataType_Size";
11689 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011690 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011691 {
11692 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11693 $ProblemKind = "Size_Of_Copying_Class";
11694 }
11695 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11696 {
11697 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11698 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11699 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011700 else
11701 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011702 # descreased size of allocable class
11703 # it has no special effects
11704 }
11705 }
11706 }
11707 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11708 "Target"=>$Type1_Pure{"Name"},
11709 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011710 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011711 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011712 }
11713 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011714 if(defined $Type1_Pure{"BaseType"}
11715 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011716 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011717 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11718 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011719 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011720 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11721 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011722 }
11723 }
11724 }
11725 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11726 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11727 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11728 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11729 { # detect removed and renamed fields
11730 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11731 next if(not $Member_Name);
11732 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);
11733 if($MemberPair_Pos eq "lost")
11734 {
11735 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11736 {
11737 if(isUnnamed($Member_Name))
11738 { # support for old-version dumps
11739 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011740 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011741 next;
11742 }
11743 }
11744 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11745 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011746 $RenamedField{$Member_Pos} = $RenamedTo;
11747 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011748 }
11749 else
11750 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011751 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011752 }
11753 }
11754 elsif($Type1_Pure{"Type"} eq "Enum")
11755 {
11756 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11757 next if($Member_Value1 eq "");
11758 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11759 if($MemberPair_Pos ne "lost")
11760 { # renamed
11761 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11762 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11763 if($MemberPair_Pos_Rev eq "lost")
11764 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011765 $RenamedField{$Member_Pos} = $RenamedTo;
11766 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011767 }
11768 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011769 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011770 }
11771 }
11772 else
11773 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011774 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011775 }
11776 }
11777 }
11778 else
11779 { # related
11780 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11781 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11782 }
11783 }
11784 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11785 { # detect added fields
11786 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11787 next if(not $Member_Name);
11788 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);
11789 if($MemberPair_Pos eq "lost")
11790 {
11791 if(isUnnamed($Member_Name))
11792 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011793 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011794 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011795 next;
11796 }
11797 }
11798 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11799 {
11800 if(not $RenamedField_Rev{$Member_Pos})
11801 { # added
11802 $AddedField{$Member_Pos}=1;
11803 }
11804 }
11805 }
11806 }
11807 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11808 { # detect moved fields
11809 my (%RelPos, %RelPosName, %AbsPos) = ();
11810 my $Pos = 0;
11811 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11812 { # relative positions in 1st version
11813 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11814 next if(not $Member_Name);
11815 if(not $RemovedField{$Member_Pos})
11816 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011817 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011818 $RelPosName{1}{$Pos} = $Member_Name;
11819 $AbsPos{1}{$Pos++} = $Member_Pos;
11820 }
11821 }
11822 $Pos = 0;
11823 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11824 { # relative positions in 2nd version
11825 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11826 next if(not $Member_Name);
11827 if(not $AddedField{$Member_Pos})
11828 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011829 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011830 $RelPosName{2}{$Pos} = $Member_Name;
11831 $AbsPos{2}{$Pos++} = $Member_Pos;
11832 }
11833 }
11834 foreach my $Member_Name (keys(%{$RelPos{1}}))
11835 {
11836 my $RPos1 = $RelPos{1}{$Member_Name};
11837 my $AbsPos1 = $NameToPosA{$Member_Name};
11838 my $Member_Name2 = $Member_Name;
11839 if(my $RenamedTo = $RenamedField{$AbsPos1})
11840 { # renamed
11841 $Member_Name2 = $RenamedTo;
11842 }
11843 my $RPos2 = $RelPos{2}{$Member_Name2};
11844 if($RPos2 ne "" and $RPos1 ne $RPos2)
11845 { # different relative positions
11846 my $AbsPos2 = $NameToPosB{$Member_Name2};
11847 if($AbsPos1 ne $AbsPos2)
11848 { # different absolute positions
11849 my $ProblemType = "Moved_Field";
11850 if(not isPublic(\%Type1_Pure, $AbsPos1))
11851 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011852 if($Level eq "Source") {
11853 next;
11854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011855 $ProblemType = "Moved_Private_Field";
11856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011857 if($Level eq "Binary"
11858 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011859 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011860 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011861 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011862 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011863 if($MemSize1 ne $MemSize2) {
11864 $ProblemType .= "_And_Size";
11865 }
11866 }
11867 if($ProblemType eq "Moved_Private_Field") {
11868 next;
11869 }
11870 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11871 "Target"=>$Member_Name,
11872 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011873 "Old_Value"=>$RPos1,
11874 "New_Value"=>$RPos2 );
11875 }
11876 }
11877 }
11878 }
11879 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011880 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011881 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11882 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011883 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011884 if(my $RenamedTo = $RenamedField{$Member_Pos})
11885 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011886 if(defined $Constants{2}{$Member_Name})
11887 {
11888 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11889 { # define OLD NEW
11890 next; # Safe
11891 }
11892 }
11893
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011894 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11895 {
11896 if(isPublic(\%Type1_Pure, $Member_Pos))
11897 {
11898 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11899 "Target"=>$Member_Name,
11900 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011901 "Old_Value"=>$Member_Name,
11902 "New_Value"=>$RenamedTo );
11903 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011904 elsif(isReserved($Member_Name))
11905 {
11906 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11907 "Target"=>$Member_Name,
11908 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011909 "Old_Value"=>$Member_Name,
11910 "New_Value"=>$RenamedTo );
11911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011912 }
11913 elsif($Type1_Pure{"Type"} eq "Enum")
11914 {
11915 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11916 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11917 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011918 "Old_Value"=>$Member_Name,
11919 "New_Value"=>$RenamedTo );
11920 }
11921 }
11922 elsif($RemovedField{$Member_Pos})
11923 { # removed
11924 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11925 {
11926 my $ProblemType = "Removed_Field";
11927 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011928 or isUnnamed($Member_Name))
11929 {
11930 if($Level eq "Source") {
11931 next;
11932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011933 $ProblemType = "Removed_Private_Field";
11934 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011935 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011936 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011937 {
11938 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11939 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011940 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 +040011941 { # changed offset
11942 $ProblemType .= "_And_Layout";
11943 }
11944 }
11945 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11946 { # affected size
11947 $ProblemType .= "_And_Size";
11948 }
11949 }
11950 if($ProblemType eq "Removed_Private_Field") {
11951 next;
11952 }
11953 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11954 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011955 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011956 }
11957 elsif($Type2_Pure{"Type"} eq "Union")
11958 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011959 if($Level eq "Binary"
11960 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011961 {
11962 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11963 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011964 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 }
11966 else
11967 {
11968 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11969 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011970 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011971 }
11972 }
11973 elsif($Type1_Pure{"Type"} eq "Enum")
11974 {
11975 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11976 "Target"=>$Member_Name,
11977 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011978 "Old_Value"=>$Member_Name );
11979 }
11980 }
11981 else
11982 { # changed
11983 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11984 if($Type1_Pure{"Type"} eq "Enum")
11985 {
11986 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11987 next if($Member_Value1 eq "");
11988 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11989 next if($Member_Value2 eq "");
11990 if($Member_Value1 ne $Member_Value2)
11991 {
11992 my $ProblemType = "Enum_Member_Value";
11993 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11994 $ProblemType = "Enum_Last_Member_Value";
11995 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011996 if($SkipConstants{1}{$Member_Name}) {
11997 $ProblemType = "Enum_Private_Member_Value";
11998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011999 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12000 "Target"=>$Member_Name,
12001 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012002 "Old_Value"=>$Member_Value1,
12003 "New_Value"=>$Member_Value2 );
12004 }
12005 }
12006 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12007 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012008 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12009 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12010
12011 if($Access1 ne "private"
12012 and $Access2 eq "private")
12013 {
12014 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12015 "Target"=>$Member_Name,
12016 "Type_Name"=>$Type1_Pure{"Name"});
12017 }
12018 elsif($Access1 ne "protected"
12019 and $Access1 ne "private"
12020 and $Access2 eq "protected")
12021 {
12022 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12023 "Target"=>$Member_Name,
12024 "Type_Name"=>$Type1_Pure{"Name"});
12025 }
12026
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012027 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12028 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012029 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012030 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12031 $SizeV1 = $BSize1;
12032 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012033 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012034 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12035 $SizeV2 = $BSize2;
12036 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012037 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12038 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012039 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012040 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012041 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012042 {
12043 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12044 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12045 { # field size change (including anon-structures and unions)
12046 # - same types
12047 # - unnamed types
12048 # - bitfields
12049 my $ProblemType = "Field_Size";
12050 if(not isPublic(\%Type1_Pure, $Member_Pos)
12051 or isUnnamed($Member_Name))
12052 { # should not be accessed by applications, goes to "Low Severity"
12053 # example: "abidata" members in GStreamer types
12054 $ProblemType = "Private_".$ProblemType;
12055 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012056 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 +040012057 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012058 if($Type2_Pure{"Type"} ne "Union"
12059 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012060 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012061 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 +040012062 { # changed offset
12063 $ProblemType .= "_And_Layout";
12064 }
12065 }
12066 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12067 $ProblemType .= "_And_Type_Size";
12068 }
12069 }
12070 if($ProblemType eq "Private_Field_Size")
12071 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012072 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012073 if($ProblemType eq "Field_Size")
12074 {
12075 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12076 { # Low severity
12077 $ProblemType = "Struct_Field_Size_Increased";
12078 }
12079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080 if($ProblemType)
12081 { # register a problem
12082 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12083 "Target"=>$Member_Name,
12084 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 "Old_Size"=>$SizeV1,
12086 "New_Size"=>$SizeV2);
12087 }
12088 }
12089 }
12090 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12091 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12092 { # do NOT check bitfield type changes
12093 next;
12094 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012095 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012096 {
12097 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12098 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12099 {
12100 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12101 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012102 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012103 }
12104 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12105 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12106 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012107 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012108 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012109 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012110 }
12111 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012112 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12113 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012114 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012115 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12116 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012117
12118 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012120 or $ProblemType eq "Field_Type_And_Size"
12121 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012122 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012123 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012124 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012125 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012126 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012127 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012128 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012129 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012130 }
12131 }
12132 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12133 {
12134 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012135 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012136 }
12137 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012138 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012139 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012140 }
12141 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12142 {
12143 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012144 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012145 }
12146 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012147 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012148 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012149 }
12150 }
12151 }
12152
12153 if($Level eq "Source")
12154 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012155 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012156 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012157 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12158 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012159
12160 if($ProblemType eq "Field_Type")
12161 {
12162 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012163 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012164 }
12165 }
12166 }
12167 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012168
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012169 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012170 {
12171 my $ProblemType_Init = $ProblemType;
12172 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012173 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012174 if(not isPublic(\%Type1_Pure, $Member_Pos)
12175 or isUnnamed($Member_Name)) {
12176 $ProblemType = "Private_".$ProblemType;
12177 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012178 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 +040012179 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012180 if($Type2_Pure{"Type"} ne "Union"
12181 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012182 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012183 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 +040012184 { # changed offset
12185 $ProblemType .= "_And_Layout";
12186 }
12187 }
12188 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12189 $ProblemType .= "_And_Type_Size";
12190 }
12191 }
12192 }
12193 else
12194 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012195 # TODO: Private_Field_Type rule?
12196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 if(not isPublic(\%Type1_Pure, $Member_Pos)
12198 or isUnnamed($Member_Name)) {
12199 next;
12200 }
12201 }
12202 if($ProblemType eq "Private_Field_Type_And_Size")
12203 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012204 }
12205 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12206 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012207 "Type_Name"=>$Type1_Pure{"Name"});
12208
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012209 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012210 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012211 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012212 }
12213 }
12214 if(not isPublic(\%Type1_Pure, $Member_Pos))
12215 { # do NOT check internal type changes
12216 next;
12217 }
12218 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012219 { # checking member type changes
12220 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12221
12222 my %DupProblems = ();
12223
12224 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012226 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012227 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012228 if(not defined $AllAffected)
12229 {
12230 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12231 next;
12232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012233 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012234
12235 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12236 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12237
12238 if(not defined $AllAffected)
12239 {
12240 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012241 }
12242 }
12243 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012244
12245 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012246 }
12247 }
12248 }
12249 }
12250 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12251 { # checking added members, public and private
12252 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12253 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012254 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012255 if($AddedField{$Member_Pos})
12256 { # added
12257 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12258 {
12259 my $ProblemType = "Added_Field";
12260 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012261 or isUnnamed($Member_Name))
12262 {
12263 if($Level eq "Source") {
12264 next;
12265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 $ProblemType = "Added_Private_Field";
12267 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012268 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012269 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012270 {
12271 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12272 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012273 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 +040012274 { # changed offset
12275 $ProblemType .= "_And_Layout";
12276 }
12277 }
12278 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12279 $ProblemType .= "_And_Size";
12280 }
12281 }
12282 if($ProblemType eq "Added_Private_Field")
12283 { # skip added private fields
12284 next;
12285 }
12286 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12287 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012288 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289 }
12290 elsif($Type2_Pure{"Type"} eq "Union")
12291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012292 if($Level eq "Binary"
12293 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012294 {
12295 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12296 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012297 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298 }
12299 else
12300 {
12301 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12302 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012303 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
12305 }
12306 elsif($Type2_Pure{"Type"} eq "Enum")
12307 {
12308 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12309 next if($Member_Value eq "");
12310 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12311 "Target"=>$Member_Name,
12312 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012313 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012314 }
12315 }
12316 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012317
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012318 if($Type1_Pure{"Type"} eq "FuncPtr")
12319 {
12320 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12321 {
12322 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12323 next;
12324 }
12325
12326 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12327 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12328
12329 my $PName = "p".$PPos;
12330
12331 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12332 my %DupProblems = ();
12333
12334 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12335 {
12336 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12337 {
12338 if(not defined $AllAffected)
12339 {
12340 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12341 next;
12342 }
12343 }
12344
12345 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12346 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12347
12348 if(not defined $AllAffected)
12349 {
12350 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12351 }
12352 }
12353 }
12354
12355 %DupProblems = ();
12356 }
12357 }
12358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012359 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012360 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012361}
12362
12363sub isUnnamed($) {
12364 return $_[0]=~/\Aunnamed\d+\Z/;
12365}
12366
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012367sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012368{
12369 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012370 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12371 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12372 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12373 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012374 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012375 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012376 }
12377 return $TypeName;
12378}
12379
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012380sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012381{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012382 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012383 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012384 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12385 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12388 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012389 return () if(not $Type{"Type"});
12390 if($Type{"Type"} ne $Type_Type)
12391 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012392 return () if(not $Type{"BaseType"});
12393 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012395 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012396 return %Type;
12397}
12398
12399my %TypeSpecAttributes = (
12400 "Const" => 1,
12401 "Volatile" => 1,
12402 "ConstVolatile" => 1,
12403 "Restrict" => 1,
12404 "Typedef" => 1
12405);
12406
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012407sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012408{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012409 my ($TypeId, $Info) = @_;
12410 if(not $TypeId or not $Info
12411 or not $Info->{$TypeId}) {
12412 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012413 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012414 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12415 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12416 }
12417 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012418 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012419 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012420 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012421 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012422 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 return %Type;
12424}
12425
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012426sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012427{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012428 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012429 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012430 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12431 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012433 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12434 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012435 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12436 my $PLevel = 0;
12437 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12438 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012439 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012440 return $PLevel if(not $Type{"BaseType"});
12441 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12442 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12443 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012444}
12445
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012446sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012447{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012448 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012450 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12451 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012453 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12454 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012455 return %Type if(not $Type{"BaseType"});
12456 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012457 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012458 return %Type;
12459}
12460
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012461sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012462{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012463 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012464 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012465 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12466 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012467 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012468 my $Qual = "";
12469 if($Type{"Type"} eq "Pointer") {
12470 $Qual .= "*";
12471 }
12472 elsif($Type{"Type"} eq "Ref") {
12473 $Qual .= "&";
12474 }
12475 elsif($Type{"Type"} eq "ConstVolatile") {
12476 $Qual .= "const volatile";
12477 }
12478 elsif($Type{"Type"} eq "Const"
12479 or $Type{"Type"} eq "Volatile"
12480 or $Type{"Type"} eq "Restrict") {
12481 $Qual .= lc($Type{"Type"});
12482 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012483 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012484 return $BQual.$Qual;
12485}
12486
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012487sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012488{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012489 my ($TypeId, $Info) = @_;
12490 if(not $TypeId or not $Info
12491 or not $Info->{$TypeId}) {
12492 return ();
12493 }
12494 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012495 return %Type if(not $Type{"BaseType"});
12496 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012497 {
12498 if($Info->{$BTid}) {
12499 return %{$Info->{$BTid}};
12500 }
12501 else { # something is going wrong
12502 return ();
12503 }
12504 }
12505 else {
12506 return %Type;
12507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012508}
12509
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012510sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012512 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012513 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012514 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12515 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012516}
12517
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012518sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012519{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012520 my $Symbol = $_[0];
12521 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12522}
12523
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012524sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012525 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12526}
12527
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012528sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012529{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012530 my ($SInfo, $LibVersion) = @_;
12531
12532 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012533 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012534 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012535 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012536 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012537 return 1;
12538 }
12539 }
12540 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012541 if(my $ShortName = $SInfo->{"ShortName"})
12542 {
12543 if(index($ShortName,"<")!=-1
12544 and index($ShortName,">")!=-1) {
12545 return 1;
12546 }
12547 }
12548
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012549 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012550}
12551
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012552sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012553{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012554 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012555 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012556 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012557 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012558 { # class specialization
12559 return 1;
12560 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012561 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012562 { # method specialization
12563 return 1;
12564 }
12565 }
12566 return 0;
12567}
12568
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012569sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012571 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012572
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012573 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012574 { # non-public global data
12575 return 0;
12576 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012577
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012578 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012579 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012580 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012581 }
12582
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012583 if($Symbol=~/\A_Z/)
12584 {
12585 if($Symbol=~/[CD][3-4]E/) {
12586 return 0;
12587 }
12588 }
12589
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012590 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591 { # support for old ABI dumps in --headers-only mode
12592 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12593 {
12594 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12595 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012596 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012597 if(not $PType or $PType eq "Unknown") {
12598 return 0;
12599 }
12600 }
12601 }
12602 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012603 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012605 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012607 if($SkipSymbols{$LibVersion}{$Symbol})
12608 { # user defined symbols to ignore
12609 return 0;
12610 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012611
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012612 if($SymbolsListPath and not $SymbolsList{$Symbol})
12613 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012614 if(not $TargetHeadersPath or not $Header
12615 or not is_target_header($Header, 1))
12616 { # -symbols-list | -headers-list
12617 return 0;
12618 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012619 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012620
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012621 if($AppPath and not $SymbolsList_App{$Symbol})
12622 { # user defined symbols (in application)
12623 return 0;
12624 }
12625
12626 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12627
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012628 if($ClassId)
12629 {
12630 if(not isTargetType($ClassId, $LibVersion)) {
12631 return 0;
12632 }
12633 }
12634
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12636 if(not $NameSpace and $ClassId)
12637 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012638 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012639 }
12640 if($NameSpace)
12641 { # user defined namespaces to ignore
12642 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12643 return 0;
12644 }
12645 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12646 { # nested namespaces
12647 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12648 return 0;
12649 }
12650 }
12651 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012652 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012653 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012654 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012655 { # --skip-headers or <skip_headers> (not <skip_including>)
12656 if($Skip==1) {
12657 return 0;
12658 }
12659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012660 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012661 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012662 { # user defined types
12663 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12664
12665 if(not $TypesList{$CName})
12666 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012667 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12668 {
12669 $CName=~s/\A\Q$NS\E\:\://g;
12670 }
12671
12672 if(not $TypesList{$CName})
12673 {
12674 my $Found = 0;
12675
12676 while($CName=~s/\:\:.+?\Z//)
12677 {
12678 if($TypesList{$CName})
12679 {
12680 $Found = 1;
12681 last;
12682 }
12683 }
12684
12685 if(not $Found) {
12686 return 0;
12687 }
12688 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012689 }
12690 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012691
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012692 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12693 { # non-target symbols
12694 return 0;
12695 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012696 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012697 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012698 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12699 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012700 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012701 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12702 { # inline virtual methods
12703 if($Type=~/InlineVirt/) {
12704 return 1;
12705 }
12706 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12707 if(not $Allocable)
12708 { # check bases
12709 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12710 {
12711 if(not isCopyingClass($DCId, $LibVersion))
12712 { # exists a derived class without default c-tor
12713 $Allocable=1;
12714 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012716 }
12717 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012718 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012719 return 0;
12720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012721 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012722 else
12723 { # inline non-virtual methods
12724 return 0;
12725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727 }
12728 }
12729 return 1;
12730}
12731
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012732sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012733{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012734 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012735 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12736 {
12737 if(link_symbol($Symbol, 1, "+Deps"))
12738 { # linker can find a new symbol
12739 # in the old-version library
12740 # So, it's not a new symbol
12741 next;
12742 }
12743 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012744 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012745 next;
12746 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012747 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012748 }
12749}
12750
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012751sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012752{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012753 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012754 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12755 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012756 if(link_symbol($Symbol, 2, "+Deps"))
12757 { # linker can find an old symbol
12758 # in the new-version library
12759 next;
12760 }
12761 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012762 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012763 next;
12764 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012765 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012766 }
12767}
12768
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012769sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012770{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012771 my $Level = $_[0];
12772 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773 { # checking added symbols
12774 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012775 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012776 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012777 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012779 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012780 { # checking removed symbols
12781 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012782 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012783 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012784 { # skip v-tables for templates, that should not be imported by applications
12785 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012786 if(my $CName = $VTableClass{$Symbol})
12787 {
12788 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12789 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012790 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012791 next;
12792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012793 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012794
12795 if($SkipSymbols{1}{$Symbol})
12796 { # user defined symbols to ignore
12797 next;
12798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012799 }
12800 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012801 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012802 }
12803 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12804 { # symbols for pure virtual methods cannot be called by clients
12805 next;
12806 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 }
12809}
12810
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012811sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012812{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012813 my ($LibVersion, $V) = @_;
12814 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12815 return $Cache{"checkDump"}{$LibVersion}{$V};
12816 }
12817 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012818}
12819
12820sub detectAdded_H($)
12821{
12822 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012823 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12824 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012825 if($Level eq "Source")
12826 { # remove symbol version
12827 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12828 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012829
12830 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12831 { # skip artificial constructors
12832 next;
12833 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012834 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012835 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12836 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012837 next;
12838 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012839 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 next;
12841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012842 if(not defined $CompleteSignature{1}{$Symbol}
12843 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12844 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012845 if($UsedDump{2}{"SrcBin"})
12846 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012847 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012848 { # support for old and different (!) ABI dumps
12849 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12850 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012851 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012852 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012853 {
12854 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12855 {
12856 if($Lang eq "C")
12857 { # support for old ABI dumps: missed extern "C" functions
12858 next;
12859 }
12860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012862 else
12863 {
12864 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012865 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012866 next;
12867 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012868 }
12869 }
12870 }
12871 }
12872 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012873 }
12874 }
12875}
12876
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012877sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012879 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012880 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12881 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012882 if($Level eq "Source")
12883 { # remove symbol version
12884 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12885 $Symbol=$SN;
12886 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012887 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12888 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012889 next;
12890 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012891 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012892 next;
12893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012894 if(not defined $CompleteSignature{2}{$Symbol}
12895 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012896 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012897 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012898 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012899 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012900 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012901 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12902 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012904 if($CheckHeadersOnly)
12905 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012906 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12907 {
12908 if($Lang eq "C")
12909 { # support for old ABI dumps: missed extern "C" functions
12910 next;
12911 }
12912 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012913 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012914 else
12915 {
12916 if(not link_symbol($Symbol, 1, "-Deps"))
12917 { # skip removed inline symbols
12918 next;
12919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012920 }
12921 }
12922 }
12923 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012924 if(not checkDump(1, "2.15"))
12925 {
12926 if($Symbol=~/_IT_E\Z/)
12927 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12928 next;
12929 }
12930 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012931 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12932 {
12933 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12934 {
12935 if(defined $Constants{2}{$Short})
12936 {
12937 my $Val = $Constants{2}{$Short}{"Value"};
12938 if(defined $Func_ShortName{2}{$Val})
12939 { # old name defined to new
12940 next;
12941 }
12942 }
12943 }
12944
12945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 $RemovedInt{$Level}{$Symbol} = 1;
12947 if($Level eq "Source")
12948 { # search for a source-compatible equivalent
12949 setAlternative($Symbol, $Level);
12950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012951 }
12952 }
12953}
12954
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012955sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012956{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012957 my $Level = $_[0];
12958 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012959 { # checking added symbols
12960 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012961 next if($CompleteSignature{2}{$Symbol}{"Private"});
12962 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012963 if($Level eq "Binary")
12964 {
12965 if($CompleteSignature{2}{$Symbol}{"InLine"})
12966 {
12967 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12968 { # skip inline non-virtual functions
12969 next;
12970 }
12971 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012972 }
12973 else
12974 { # Source
12975 if($SourceAlternative_B{$Symbol}) {
12976 next;
12977 }
12978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012979 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012980 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012982 { # checking removed symbols
12983 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012984 next if($CompleteSignature{1}{$Symbol}{"Private"});
12985 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012986 if($Level eq "Binary")
12987 {
12988 if($CompleteSignature{1}{$Symbol}{"InLine"})
12989 {
12990 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12991 { # skip inline non-virtual functions
12992 next;
12993 }
12994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012995 }
12996 else
12997 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012998 if(my $Alt = $SourceAlternative{$Symbol})
12999 {
13000 if(defined $CompleteSignature{1}{$Alt}
13001 and $CompleteSignature{1}{$Symbol}{"Const"})
13002 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013003 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013004 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013005 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013006 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013007 }
13008 else
13009 { # do NOT show removed symbol
13010 next;
13011 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013012 }
13013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013014 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013015 }
13016}
13017
13018sub addParamNames($)
13019{
13020 my $LibraryVersion = $_[0];
13021 return if(not keys(%AddIntParams));
13022 my $SecondVersion = $LibraryVersion==1?2:1;
13023 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13024 {
13025 next if(not keys(%{$AddIntParams{$Interface}}));
13026 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013027 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013028 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13029 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013030 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013031 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13032 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13033 {
13034 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13035 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13036 }
13037 }
13038 else {
13039 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13040 }
13041 }
13042 }
13043 }
13044}
13045
13046sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013047{ # detect changed typedefs to show
13048 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013049 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13050 {
13051 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013052 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13053 if(not $BName1 or isAnon($BName1)) {
13054 next;
13055 }
13056 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13057 if(not $BName2 or isAnon($BName2)) {
13058 next;
13059 }
13060 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013061 $ChangedTypedef{$Typedef} = 1;
13062 }
13063 }
13064}
13065
13066sub get_symbol_suffix($$)
13067{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013068 my ($Symbol, $Full) = @_;
13069 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013070 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013071 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013072 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013073 if(not $Full) {
13074 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13075 }
13076 return $Suffix;
13077}
13078
13079sub get_symbol_prefix($$)
13080{
13081 my ($Symbol, $LibVersion) = @_;
13082 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13083 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13084 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013085 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013086 }
13087 return $ShortName;
13088}
13089
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013090sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013091{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013092 my $Symbol = $_[0];
13093 my $PSymbol = $Symbol;
13094 if(not defined $CompleteSignature{2}{$PSymbol}
13095 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13096 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13097 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013098 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013099 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013100 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013101 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013102 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13103 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013104 {
13105 if(defined $CompleteSignature{2}{$PSymbol}
13106 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13107 {
13108 $SourceAlternative{$Symbol} = $PSymbol;
13109 $SourceAlternative_B{$PSymbol} = $Symbol;
13110 if(not defined $CompleteSignature{1}{$PSymbol}
13111 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13112 $SourceReplacement{$Symbol} = $PSymbol;
13113 }
13114 }
13115 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013116 }
13117 else
13118 {
13119 foreach my $Sp ("KV", "VK", "K", "V")
13120 {
13121 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13122 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13123 {
13124 if(defined $CompleteSignature{2}{$PSymbol}
13125 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13126 {
13127 $SourceAlternative{$Symbol} = $PSymbol;
13128 $SourceAlternative_B{$PSymbol} = $Symbol;
13129 if(not defined $CompleteSignature{1}{$PSymbol}
13130 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13131 $SourceReplacement{$Symbol} = $PSymbol;
13132 }
13133 }
13134 }
13135 $PSymbol = $Symbol;
13136 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013137 }
13138 }
13139 }
13140 return "";
13141}
13142
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013143sub getSymKind($$)
13144{
13145 my ($Symbol, $LibVersion) = @_;
13146 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13147 {
13148 return "Global_Data";
13149 }
13150 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13151 {
13152 return "Method";
13153 }
13154 return "Function";
13155}
13156
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013157sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013158{
13159 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013160 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013161
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013162 mergeBases($Level);
13163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013165 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013166 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013167 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 next;
13169 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013170 if(defined $CompleteSignature{1}{$Symbol}
13171 and $CompleteSignature{1}{$Symbol}{"Header"})
13172 { # double-check added symbol
13173 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013174 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013175 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013176 next;
13177 }
13178 if($Symbol=~/\A(_Z|\?)/)
13179 { # C++
13180 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13181 }
13182 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13183 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013184 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13185 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013186 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013187 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013188 {
13189 if($TName_Tid{1}{$AffectedClass_Name})
13190 { # class should exist in previous version
13191 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13192 { # old v-table is NOT copied by old applications
13193 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13194 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013195 "Target"=>get_Signature($Symbol, 2),
13196 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013197 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013200 }
13201 }
13202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013203 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13204 { # check all removed exported symbols
13205 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013206 next;
13207 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013208 if(defined $CompleteSignature{2}{$Symbol}
13209 and $CompleteSignature{2}{$Symbol}{"Header"})
13210 { # double-check removed symbol
13211 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013212 }
13213 if($CompleteSignature{1}{$Symbol}{"Private"})
13214 { # skip private methods
13215 next;
13216 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013217 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013218 next;
13219 }
13220 $CheckedSymbols{$Level}{$Symbol} = 1;
13221 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13222 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013223 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13224 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013225 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013226 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13227 {
13228 if($TName_Tid{2}{$AffectedClass_Name})
13229 { # class should exist in newer version
13230 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13231 { # old v-table is NOT copied by old applications
13232 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13233 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013234 "Target"=>get_Signature($OverriddenMethod, 1),
13235 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013236 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013239 }
13240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013241 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013242 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013243 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013244 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013245 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013246 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013247 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013248 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013250 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013251 {
13252 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13253 "Target"=>$tr_name{$Symbol},
13254 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013255 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013257 else
13258 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013259 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013260 "Target"=>$tr_name{$Symbol},
13261 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013262 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013263 }
13264 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013265 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013267 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013268 {
13269 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13270 "Target"=>$tr_name{$Symbol},
13271 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013272 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013274 else
13275 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013276 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013277 "Target"=>$tr_name{$Symbol},
13278 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013279 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013280 }
13281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013282 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13283 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13284 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13285 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13286 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013287 {
13288 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013289 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013290 $ProblemType = "Global_Data_Symbol_Changed_Type";
13291 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013292 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13293 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013294 "Old_Type"=>$RTName1,
13295 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013296 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013297 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013298 }
13299 }
13300 }
13301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013302 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013304 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013305 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013306 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013308 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013309 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13310 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013311 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013312 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013313 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013314 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 }
13316 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013317 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13318 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013319 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013320 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013321 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013322 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013323 }
13324 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013325 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013326 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013327 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013328 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013330 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013331 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013332 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013333 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013335 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013336 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013337 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013339 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013340 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013341 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013342 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013343 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013344 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 { # "volatile" to non-"volatile"
13351
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013352 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013353 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013354 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013355 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013356 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013357 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013359 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013360 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013361 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013364 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013365 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013366 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13370 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013371 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 }
13375 }
13376 }
13377 }
13378 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013379 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13380 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013381 $CurrentSymbol = $Symbol;
13382
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13384 if($Level eq "Source")
13385 { # remove symbol version
13386 $Symbol=$SN;
13387 }
13388 else
13389 { # Binary
13390 if(not $SV)
13391 { # symbol without version
13392 if(my $VSym = $SymVer{1}{$Symbol})
13393 { # the symbol is linked with versioned symbol
13394 if($CompleteSignature{2}{$VSym}{"MnglName"})
13395 { # show report for symbol@ver only
13396 next;
13397 }
13398 elsif(not link_symbol($VSym, 2, "-Deps"))
13399 { # changed version: sym@v1 to sym@v2
13400 # do NOT show report for symbol
13401 next;
13402 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013403 }
13404 }
13405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 my $PSymbol = $Symbol;
13407 if($Level eq "Source"
13408 and my $S = $SourceReplacement{$Symbol})
13409 { # take a source-compatible replacement function
13410 $PSymbol = $S;
13411 }
13412 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013413 { # private symbols
13414 next;
13415 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 if(not defined $CompleteSignature{1}{$Symbol}
13417 or not defined $CompleteSignature{2}{$PSymbol})
13418 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013419 next;
13420 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13422 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13423 { # no mangled name
13424 next;
13425 }
13426 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13427 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013428 { # without a header
13429 next;
13430 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013431
13432 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13433 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13434 { # became pure
13435 next;
13436 }
13437 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13438 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13439 { # became non-pure
13440 next;
13441 }
13442
13443 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13444 { # exported, target, inline virtual and pure virtual
13445 next;
13446 }
13447 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13448 { # exported, target, inline virtual and pure virtual
13449 next;
13450 }
13451
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013452 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013453 {
13454 if($CompleteSignature{1}{$Symbol}{"Data"}
13455 and $CompleteSignature{2}{$PSymbol}{"Data"})
13456 {
13457 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13458 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13459 if(defined $Value1)
13460 {
13461 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13462 if(defined $Value2)
13463 {
13464 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13465 if($Value1 ne $Value2)
13466 {
13467 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13468 "Old_Value"=>$Value1,
13469 "New_Value"=>$Value2,
13470 "Target"=>get_Signature($Symbol, 1) );
13471 }
13472 }
13473 }
13474 }
13475 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013476
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013477 if($CompleteSignature{2}{$PSymbol}{"Private"})
13478 {
13479 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13480 "Target"=>get_Signature_M($PSymbol, 2) );
13481 }
13482 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13483 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13484 {
13485 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13486 "Target"=>get_Signature_M($PSymbol, 2) );
13487 }
13488 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13489 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13490 {
13491 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13492 "Target"=>get_Signature_M($PSymbol, 2) );
13493 }
13494
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013495 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013496 mergeVirtualTables($Symbol, $Level);
13497
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013498 if($COMPILE_ERRORS)
13499 { # if some errors occurred at the compiling stage
13500 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013502 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013503 { # missed information about parameters in newer version
13504 next;
13505 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013506 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013507 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013508 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013509 next;
13510 }
13511 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013512 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013513 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013514 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013515 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13516 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013517 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13518 "Target"=>get_Signature($Symbol, 1)
13519 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013521 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013522 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13523 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013524 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013525 "Target"=>get_Signature($Symbol, 1)
13526 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013527 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013528 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13529 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013531 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013532 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013533 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13534 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13535 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013536 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013537 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013538 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13539 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013540 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013541 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 my $ProblemType = "Virtual_Method_Position";
13543 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13544 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013545 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013546 if(isUsedClass($Class_Id, 1, $Level))
13547 {
13548 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013549 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013550 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013551 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13552 next;
13553 }
13554 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013555 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013556 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13557 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013558 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013559 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013560 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013562 }
13563 }
13564 }
13565 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013566 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13567 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013568 { # do NOT check type changes in pure virtuals
13569 next;
13570 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013571 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013572 if($Symbol=~/\A(_Z|\?)/
13573 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013574 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013575 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013577 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013578 }
13579 }
13580 else
13581 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013582 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013583 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013584 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013585 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13586 last if($PType2_Name eq "...");
13587 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13588 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013589 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013590 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013592 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13593 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013594 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13595 $ParamPos_Prev = "lost";
13596 }
13597 }
13598 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013599 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013600 }
13601 if($ParamPos_Prev eq "lost")
13602 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013603 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013604 {
13605 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013606 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013607 $ProblemType = "Added_Unnamed_Parameter";
13608 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013609 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013610 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013611 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013612 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013613 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013614 }
13615 else
13616 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013617 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013618 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013619 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013620 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13621 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013623 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013624 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013625 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013626 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013627 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013628 "Param_Type"=>$PType2_Name,
13629 "Old_Value"=>$PName_Old,
13630 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013631 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013632 }
13633 }
13634 else
13635 {
13636 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013637 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013638 $ProblemType = "Added_Middle_Unnamed_Parameter";
13639 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013640 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013641 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013642 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013643 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013644 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013645 }
13646 }
13647 }
13648 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013649 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013650 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013651 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013652 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013653 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013656 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013658 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13659 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013660 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013661 }
13662 }
13663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013664 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013665 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013666 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013667 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13668 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013669 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13670 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013672 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013674 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13675 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13677 $ParamPos_New = "lost";
13678 }
13679 }
13680 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013681 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 }
13683 if($ParamPos_New eq "lost")
13684 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013685 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 {
13687 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013688 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013689 $ProblemType = "Removed_Unnamed_Parameter";
13690 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013691 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013692 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013693 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013695 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013697 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013698 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013699 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013700 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013701 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013702 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013703 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013704 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013705 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013707 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013708 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013709 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013710 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013711 "Old_Value"=>$PName,
13712 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013713 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013714 }
13715 }
13716 else
13717 {
13718 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013719 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013720 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13721 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013722 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013723 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013724 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013725 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013726 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 }
13728 }
13729 }
13730 }
13731 }
13732 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013733 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13734 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013735 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013736
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013737 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013738 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013739 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13740 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013741 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013742
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013743 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013744 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013745 if($SubProblemType eq "Return_Type_And_Size") {
13746 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13747 }
13748 elsif($SubProblemType eq "Return_Type_Format") {
13749 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13750 }
13751 else {
13752 $ProblemTypes{"Global_Data_Type"} = 1;
13753 }
13754
13755 # quals
13756 if($SubProblemType eq "Return_Type"
13757 or $SubProblemType eq "Return_Type_And_Size"
13758 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013759 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013760 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13761 { # const to non-const
13762 if($RR==2) {
13763 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13764 }
13765 else {
13766 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13767 }
13768 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013769 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013770 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13771 { # non-const to const
13772 if($RA==2) {
13773 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13774 }
13775 else {
13776 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13777 }
13778 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013779 }
13780 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013781 }
13782 else
13783 {
13784 # quals
13785 if($SubProblemType eq "Return_Type"
13786 or $SubProblemType eq "Return_Type_And_Size"
13787 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013788 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013789 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013790 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013791 if(addedQual($Old_Value, $New_Value, "volatile"))
13792 {
13793 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13794 if($Level ne "Source"
13795 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13796 $ProblemTypes{"Return_Type"} = 1;
13797 }
13798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013800 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13801 {
13802 if($RA==2) {
13803 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13804 }
13805 else {
13806 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13807 }
13808 if($Level ne "Source"
13809 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13810 $ProblemTypes{"Return_Type"} = 1;
13811 }
13812 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013813 }
13814 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013815 if($Level eq "Binary"
13816 and not $CompleteSignature{1}{$Symbol}{"Data"})
13817 {
13818 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13819 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13820 { # if one of the architectures is unknown
13821 # then set other arhitecture to unknown too
13822 ($Arch1, $Arch2) = ("unknown", "unknown");
13823 }
13824 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013825 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013826 {
13827 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13828 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13829 }
13830 else
13831 {
13832 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13833 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13834 }
13835
13836 if($SubProblemType eq "Return_Type_Became_Void")
13837 {
13838 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13839 { # parameters stack has been affected
13840 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013841 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013842 }
13843 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013844 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013845 }
13846 }
13847 }
13848 elsif($SubProblemType eq "Return_Type_From_Void")
13849 {
13850 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13851 { # parameters stack has been affected
13852 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013853 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013854 }
13855 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013856 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013857 }
13858 }
13859 }
13860 elsif($SubProblemType eq "Return_Type"
13861 or $SubProblemType eq "Return_Type_And_Size"
13862 or $SubProblemType eq "Return_Type_Format")
13863 {
13864 if($Conv1{"Method"} ne $Conv2{"Method"})
13865 {
13866 if($Conv1{"Method"} eq "stack")
13867 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013868 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013869 }
13870 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013871 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013872 }
13873 }
13874 else
13875 {
13876 if($Conv1{"Method"} eq "reg")
13877 {
13878 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13879 {
13880 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013881 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013882 }
13883 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013884 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013885 }
13886 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013887 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013888 }
13889 }
13890 }
13891 }
13892 }
13893 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013894
13895 if(not keys(%ProblemTypes))
13896 { # default
13897 $ProblemTypes{$SubProblemType} = 1;
13898 }
13899
13900 foreach my $ProblemType (keys(%ProblemTypes))
13901 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013902 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013904 }
13905 if($ReturnType1_Id and $ReturnType2_Id)
13906 {
13907 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013908 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13909
13910 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013911
13912 if($CompleteSignature{1}{$Symbol}{"Data"})
13913 {
13914 if($Level eq "Binary")
13915 {
13916 if(get_PLevel($ReturnType1_Id, 1)==0)
13917 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013918 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013919 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013920
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013921 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13922 {
13923 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013924 {
13925 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13926 {
13927 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13928 last;
13929 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013930 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013931 }
13932 }
13933 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013934 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013935 {
13936 if(defined $GlobalDataObject{1}{$Symbol}
13937 and defined $GlobalDataObject{2}{$Symbol})
13938 {
13939 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13940 my $New_Size = $GlobalDataObject{2}{$Symbol};
13941 if($Old_Size!=$New_Size)
13942 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013943 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013944 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013945 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013946 }
13947 }
13948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013949 }
13950 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013951
13952 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013953 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013954 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013955 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013956 my $NewLocation = "retval";
13957 if($SubLocation and $SubLocation ne "retval") {
13958 $NewLocation = "retval->".$SubLocation;
13959 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013960 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13961 }
13962 }
13963
13964 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13965 {
13966 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13967 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013968 my $NewLocation = "retval";
13969 if($SubLocation and $SubLocation ne "retval") {
13970 $NewLocation = "retval->".$SubLocation;
13971 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013972 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013973 }
13974 }
13975 }
13976
13977 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013978 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13979 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13980 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013981 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013982 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013983 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13984 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013985 if($ThisPtr1_Id and $ThisPtr2_Id)
13986 {
13987 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013988 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13989 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013990 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013991 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013992 {
13993 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013994 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013995 }
13996 }
13997 }
13998 }
13999 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014000 if($Level eq "Binary") {
14001 mergeVTables($Level);
14002 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014003 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14004 $CheckedSymbols{$Level}{$Symbol} = 1;
14005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014006}
14007
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014008sub rmQuals($$)
14009{
14010 my ($Value, $Qual) = @_;
14011 if(not $Qual) {
14012 return $Value;
14013 }
14014 if($Qual eq "all")
14015 { # all quals
14016 $Qual = "const|volatile|restrict";
14017 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014018 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014019 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014020 }
14021 return $Value;
14022}
14023
14024sub cmpBTypes($$$$)
14025{
14026 my ($T1, $T2, $V1, $V2) = @_;
14027 $T1 = uncover_typedefs($T1, $V1);
14028 $T2 = uncover_typedefs($T2, $V2);
14029 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14030}
14031
14032sub addedQual($$$)
14033{
14034 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014035 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014036}
14037
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014038sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014039{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014040 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014041 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014042}
14043
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014044sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014045{
14046 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14047 $Old_Value = uncover_typedefs($Old_Value, $V1);
14048 $New_Value = uncover_typedefs($New_Value, $V2);
14049 if($Old_Value eq $New_Value)
14050 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014051 return 0;
14052 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014053 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014054 { # without a qual
14055 return 0;
14056 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014057 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014058 { # became non-qual
14059 return 1;
14060 }
14061 else
14062 {
14063 my @BQ1 = getQualModel($Old_Value, $Qual);
14064 my @BQ2 = getQualModel($New_Value, $Qual);
14065 foreach (0 .. $#BQ1)
14066 { # removed qual
14067 if($BQ1[$_]==1
14068 and $BQ2[$_]!=1)
14069 {
14070 return 2;
14071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014072 }
14073 }
14074 return 0;
14075}
14076
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014077sub getQualModel($$)
14078{
14079 my ($Value, $Qual) = @_;
14080 if(not $Qual) {
14081 return $Value;
14082 }
14083
14084 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014085 while($Value=~/(\w+)/ and $1 ne $Qual) {
14086 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014087 }
14088 $Value=~s/[^\*\&\w]+//g;
14089
14090 # modeling
14091 # int*const*const == 011
14092 # int**const == 001
14093 my @Model = ();
14094 my @Elems = split(/[\*\&]/, $Value);
14095 if(not @Elems) {
14096 return (0);
14097 }
14098 foreach (@Elems)
14099 {
14100 if($_ eq $Qual) {
14101 push(@Model, 1);
14102 }
14103 else {
14104 push(@Model, 0);
14105 }
14106 }
14107
14108 return @Model;
14109}
14110
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014111my %StringTypes = map {$_=>1} (
14112 "char*",
14113 "char const*"
14114);
14115
14116my %CharTypes = map {$_=>1} (
14117 "char",
14118 "char const"
14119);
14120
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014121sub showVal($$$)
14122{
14123 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014124 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014125 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014126 if(substr($Value, 0, 2) eq "_Z")
14127 {
14128 if(my $Unmangled = $tr_name{$Value}) {
14129 return $Unmangled;
14130 }
14131 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014132 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014133 { # strings
14134 return "\"$Value\"";
14135 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014136 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014137 { # characters
14138 return "\'$Value\'";
14139 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014140 if($Value eq "")
14141 { # other
14142 return "\'\'";
14143 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014144 return $Value;
14145}
14146
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014147sub getRegs($$$)
14148{
14149 my ($LibVersion, $Symbol, $Pos) = @_;
14150
14151 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14152 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014153 my %Regs = ();
14154 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14155 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014156 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014157 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14158 }
14159 }
14160
14161 return join(", ", sort keys(%Regs));
14162 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014163 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14164 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14165 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14166 {
14167 return "unknown";
14168 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014169
14170 return undef;
14171}
14172
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014173sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014174{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014175 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014176 if(not $Symbol) {
14177 return;
14178 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014179 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14180 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14181 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14182 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014183 if(not $PType1_Id
14184 or not $PType2_Id) {
14185 return;
14186 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014187
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014188 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014189 { # do not merge "this"
14190 if($PName1 eq "this" or $PName2 eq "this") {
14191 return;
14192 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014193 }
14194
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014195 my %Type1 = get_Type($PType1_Id, 1);
14196 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014197
14198 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14199
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014200 my %BaseType1 = get_BaseType($PType1_Id, 1);
14201 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014202
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014203 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014204
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014205 if($Level eq "Binary")
14206 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014207 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014208 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14209 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14210 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14211 {
14212 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014213 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014214 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014215 }
14216 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14217 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14218 {
14219 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014220 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014221 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014223 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014224
14225 if(defined $UsedDump{1}{"DWARF"}
14226 and defined $UsedDump{2}{"DWARF"})
14227 {
14228 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14229 {
14230 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14231 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014232
14233 if($Old_Regs ne "unknown"
14234 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014235 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014236 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014237 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014238 if($Old_Regs ne $New_Regs)
14239 {
14240 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14241 "Target"=>$PName1,
14242 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14243 "Old_Value"=>$Old_Regs,
14244 "New_Value"=>$New_Regs );
14245 }
14246 }
14247 elsif($Old_Regs and not $New_Regs)
14248 {
14249 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014250 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014251 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014252 "Old_Value"=>$Old_Regs );
14253 }
14254 elsif(not $Old_Regs and $New_Regs)
14255 {
14256 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14257 "Target"=>$PName1,
14258 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014259 "New_Value"=>$New_Regs );
14260 }
14261 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014262
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014263 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14264 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14265 {
14266 if($Old_Offset ne $New_Offset)
14267 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014268 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14269 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14270
14271 $Old_Offset = $Old_Offset - $Start1;
14272 $New_Offset = $New_Offset - $Start2;
14273
14274 if($Old_Offset ne $New_Offset)
14275 {
14276 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14277 "Target"=>$PName1,
14278 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14279 "Old_Value"=>$Old_Offset,
14280 "New_Value"=>$New_Offset );
14281 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014282 }
14283 }
14284 }
14285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014286 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014287 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14288 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014289 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014290 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014291 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14292 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014293 if(not checkDump(1, "2.13")
14294 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014295 { # support for old ABI dumps
14296 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014297 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014298 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014299 and $Value_Old eq "false" and $Value_New eq "0")
14300 { # int class::method ( bool p = 0 );
14301 # old ABI dumps: "false"
14302 # new ABI dumps: "0"
14303 $Value_Old = "0";
14304 }
14305 }
14306 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014307 if(not checkDump(1, "2.18")
14308 and checkDump(2, "2.18"))
14309 { # support for old ABI dumps
14310 if(not defined $Value_Old
14311 and substr($Value_New, 0, 2) eq "_Z") {
14312 $Value_Old = $Value_New;
14313 }
14314 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014315 if(defined $Value_Old)
14316 {
14317 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14318 if(defined $Value_New)
14319 {
14320 $Value_New = showVal($Value_New, $PType2_Id, 2);
14321 if($Value_Old ne $Value_New)
14322 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014323 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014324 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014325 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014326 "Old_Value"=>$Value_Old,
14327 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014328 }
14329 }
14330 else
14331 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014332 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014333 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014334 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014335 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336 }
14337 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014338 elsif(defined $Value_New)
14339 {
14340 $Value_New = showVal($Value_New, $PType2_Id, 2);
14341 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14342 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014343 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014344 "New_Value"=>$Value_New );
14345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014346 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014347
14348 if($ChkRnmd)
14349 {
14350 if($PName1 and $PName2 and $PName1 ne $PName2
14351 and $PType1_Id!=-1 and $PType2_Id!=-1
14352 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14353 { # except unnamed "..." value list (Id=-1)
14354 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14355 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014356 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014357 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14358 "Old_Value"=>$PName1,
14359 "New_Value"=>$PName2,
14360 "New_Signature"=>get_Signature($Symbol, 2) );
14361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014362 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014364 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014365 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014367 foreach my $SubProblemType (keys(%SubProblems))
14368 { # add new problems, remove false alarms
14369 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14370 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014371
14372 # quals
14373 if($SubProblemType eq "Parameter_Type"
14374 or $SubProblemType eq "Parameter_Type_And_Size"
14375 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014376 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014377 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014378 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014379 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014380 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014381 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014382 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14383 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14384 }
14385 }
14386 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14387 {
14388 if(removedQual($Old_Value, $New_Value, "volatile")) {
14389 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014390 }
14391 }
14392 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14393 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14394 { # int to "int const"
14395 delete($SubProblems{$SubProblemType});
14396 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014397 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014398 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14399 { # "int const" to int
14400 delete($SubProblems{$SubProblemType});
14401 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014402 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14403 { # "const" to non-"const"
14404 if($RR==2) {
14405 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14406 }
14407 else {
14408 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14409 }
14410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411 }
14412 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014413
14414 if($Level eq "Source")
14415 {
14416 foreach my $SubProblemType (keys(%SubProblems))
14417 {
14418 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14419 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14420
14421 if($SubProblemType eq "Parameter_Type")
14422 {
14423 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14424 delete($SubProblems{$SubProblemType});
14425 }
14426 }
14427 }
14428 }
14429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014430 foreach my $SubProblemType (keys(%SubProblems))
14431 { # modify/register problems
14432 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14433 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014434 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14435 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014437 my $NewProblemType = $SubProblemType;
14438 if($Old_Value eq "..." and $New_Value ne "...")
14439 { # change from "..." to "int"
14440 if($ParamPos1==0)
14441 { # ISO C requires a named argument before "..."
14442 next;
14443 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014444 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014445 }
14446 elsif($New_Value eq "..." and $Old_Value ne "...")
14447 { # change from "int" to "..."
14448 if($ParamPos2==0)
14449 { # ISO C requires a named argument before "..."
14450 next;
14451 }
14452 $NewProblemType = "Parameter_Became_VaList";
14453 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014454 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014455 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014456 {
14457 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014458 if($Arch1 eq "unknown"
14459 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014460 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014461 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014462 ($Arch1, $Arch2) = ("unknown", "unknown");
14463 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014464 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014465 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014466 { # real
14467 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14468 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14469 }
14470 else
14471 { # model
14472 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14473 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14474 }
14475 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014477 if($Conv1{"Method"} eq "stack")
14478 {
14479 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14480 $NewProblemType = "Parameter_Type_And_Stack";
14481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014482 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014483 elsif($Conv1{"Method"} eq "reg")
14484 {
14485 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14486 $NewProblemType = "Parameter_Type_And_Register";
14487 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014488 }
14489 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014490 elsif($Conv1{"Method"} ne "unknown"
14491 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014492 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014493 if($Conv1{"Method"} eq "stack") {
14494 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014495 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014496 elsif($Conv1{"Method"} eq "register") {
14497 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014498 }
14499 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014500 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14501 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014502 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014503 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014504 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014505 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014506 "New_Signature"=>get_Signature($Symbol, 2) );
14507 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014509
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014513 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14514 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014515 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014516 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014517 {
14518 my $NewProblemType = $SubProblemType;
14519 if($SubProblemType eq "DataType_Size")
14520 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014521 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014522 { # stack has been affected
14523 $NewProblemType = "DataType_Size_And_Stack";
14524 }
14525 }
14526 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014527 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014528 }
14529 }
14530}
14531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014532sub find_ParamPair_Pos_byName($$$)
14533{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014534 my ($Name, $Symbol, $LibVersion) = @_;
14535 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014537 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14538 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014539 {
14540 return $ParamPos;
14541 }
14542 }
14543 return "lost";
14544}
14545
14546sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14547{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014548 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014549 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014550 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014551 {
14552 next if($Order eq "backward" and $ParamPos>$MediumPos);
14553 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014554 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14555 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014556 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014557 push(@Positions, $ParamPos);
14558 }
14559 }
14560 return @Positions;
14561}
14562
14563sub getTypeIdByName($$)
14564{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014565 my ($TypeName, $LibVersion) = @_;
14566 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014567}
14568
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014569sub diffTypes($$$)
14570{
14571 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14572 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14573 }
14574 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14575 { # skip recursive declarations
14576 return 0;
14577 }
14578
14579 pushType($_[0], $_[1], \@RecurTypes_Diff);
14580 my $Diff = diffTypes_I(@_);
14581 pop(@RecurTypes_Diff);
14582
14583 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14584}
14585
14586sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014587{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014588 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014589
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014590 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14591 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014592
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014593 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14594 { # equal types
14595 return 0;
14596 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014597 if($Type1_Pure{"Name"} eq "void")
14598 { # from void* to something
14599 return 0;
14600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014601 if($Type1_Pure{"Name"}=~/\*/
14602 or $Type2_Pure{"Name"}=~/\*/)
14603 { # compared in detectTypeChange()
14604 return 0;
14605 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014607 my %FloatType = map {$_=>1} (
14608 "float",
14609 "double",
14610 "long double"
14611 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014612
14613 my $T1 = $Type1_Pure{"Type"};
14614 my $T2 = $Type2_Pure{"Type"};
14615
14616 if($T1 eq "Struct"
14617 and $T2 eq "Class")
14618 { # compare as data structures
14619 $T2 = "Struct";
14620 }
14621
14622 if($T1 eq "Class"
14623 and $T2 eq "Struct")
14624 { # compare as data structures
14625 $T1 = "Struct";
14626 }
14627
14628 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014629 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014630 if($T1 eq "Intrinsic"
14631 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014632 { # "int" to "enum"
14633 return 0;
14634 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014635 elsif($T2 eq "Intrinsic"
14636 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014637 { # "enum" to "int"
14638 return 0;
14639 }
14640 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014641 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014642 # ...
14643 return 1;
14644 }
14645 }
14646 else
14647 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014648 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 {
14650 if($FloatType{$Type1_Pure{"Name"}}
14651 or $FloatType{$Type2_Pure{"Name"}})
14652 { # "float" to "double"
14653 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014654 if($Level eq "Source")
14655 { # Safe
14656 return 0;
14657 }
14658 else {
14659 return 1;
14660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014661 }
14662 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014663 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014664 {
14665 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14666 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014667 if(not @Membs1
14668 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014669 { # private
14670 return 0;
14671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014672 if($#Membs1!=$#Membs2)
14673 { # different number of elements
14674 return 1;
14675 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014676 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014677 {
14678 foreach my $Pos (@Membs1)
14679 { # compare elements by name and value
14680 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14681 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14682 { # different names
14683 return 1;
14684 }
14685 }
14686 }
14687 else
14688 {
14689 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014690 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014691 if($Level eq "Source")
14692 {
14693 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14694 { # different names
14695 return 1;
14696 }
14697 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014698
14699 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14700 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14701
14702 if($MT1{"Name"} ne $MT2{"Name"}
14703 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14704 {
14705 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14706 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14707
14708 if($PL1 ne $PL2)
14709 { # different pointer level
14710 return 1;
14711 }
14712
14713 # compare base types
14714 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14715 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14716
14717 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14718 { # different types
14719 return 1;
14720 }
14721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014722 }
14723 }
14724 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014725 else
14726 {
14727 # TODO: arrays, etc.
14728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014729 }
14730 return 0;
14731}
14732
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014733sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014734{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014735 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014736 if(not $Type1_Id or not $Type2_Id) {
14737 return ();
14738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014739 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014740 my %Type1 = get_Type($Type1_Id, 1);
14741 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014742 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14743 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014744
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014745 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14746 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 +040014747
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014748 if(defined $UsedDump{1}{"DWARF"})
14749 {
14750 if($Type1_Pure{"Name"} eq "__unknown__"
14751 or $Type2_Pure{"Name"} eq "__unknown__"
14752 or $Type1_Base{"Name"} eq "__unknown__"
14753 or $Type2_Base{"Name"} eq "__unknown__")
14754 { # Error ABI dump
14755 return ();
14756 }
14757 }
14758
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014759 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14760 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014761 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14762 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14763 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14764 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14765 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14766 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14767 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014768 if($Type1{"Name"} eq $Type2{"Name"})
14769 {
14770 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14771 { # will be reported in mergeTypes() as typedef problem
14772 return ();
14773 }
14774 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14775 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14776 if(%Typedef_1 and %Typedef_2)
14777 {
14778 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14779 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14780 { # const Typedef
14781 return ();
14782 }
14783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014784 }
14785 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14786 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014787 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014788 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14789 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014790 {
14791 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14792 "Old_Value"=>$Type1_Base{"Name"},
14793 "New_Value"=>$Type2_Base{"Name"},
14794 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014795 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014796 }
14797 else
14798 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014799 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014800 { # format change
14801 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14802 "Old_Value"=>$Type1_Base{"Name"},
14803 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014804 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014805 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014806 }
14807 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14808 {
14809 %{$LocalProblems{$Prefix."_BaseType"}}=(
14810 "Old_Value"=>$Type1_Base{"Name"},
14811 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014812 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014813 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014814 }
14815 }
14816 }
14817 }
14818 elsif($Type1{"Name"} ne $Type2{"Name"})
14819 { # type change
14820 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14821 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014822 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014823 and $Type1_Pure{"Name"} eq "void")
14824 {
14825 %{$LocalProblems{"Return_Type_From_Void"}}=(
14826 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014827 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014829 elsif($Prefix eq "Return"
14830 and $Type2_Pure{"Name"} eq "void")
14831 {
14832 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14833 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014834 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014836 else
14837 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014838 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014839 and $Type1{"Size"} and $Type2{"Size"}
14840 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014841 {
14842 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14843 "Old_Value"=>$Type1{"Name"},
14844 "New_Value"=>$Type2{"Name"},
14845 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014846 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014847 }
14848 else
14849 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014850 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014851 { # format change
14852 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14853 "Old_Value"=>$Type1{"Name"},
14854 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014855 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014856 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014857 }
14858 elsif(tNameLock($Type1_Id, $Type2_Id))
14859 { # FIXME: correct this condition
14860 %{$LocalProblems{$Prefix."_Type"}}=(
14861 "Old_Value"=>$Type1{"Name"},
14862 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014863 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014864 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865 }
14866 }
14867 }
14868 }
14869 }
14870 if($Type1_PLevel!=$Type2_PLevel)
14871 {
14872 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14873 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14874 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014875 if($Level eq "Source")
14876 {
14877 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014878 "Old_Value"=>$Type1_PLevel,
14879 "New_Value"=>$Type2_PLevel);
14880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014881 else
14882 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014883 if($Type2_PLevel>$Type1_PLevel)
14884 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014885 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14886 "Old_Value"=>$Type1_PLevel,
14887 "New_Value"=>$Type2_PLevel);
14888 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014889 else
14890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014891 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14892 "Old_Value"=>$Type1_PLevel,
14893 "New_Value"=>$Type2_PLevel);
14894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014895 }
14896 }
14897 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014898 if($Type1_Pure{"Type"} eq "Array"
14899 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014900 { # base_type[N] -> base_type[N]
14901 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014902 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014903 foreach my $SubProblemType (keys(%SubProblems))
14904 {
14905 $SubProblemType=~s/_Type/_BaseType/g;
14906 next if(defined $LocalProblems{$SubProblemType});
14907 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14908 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14909 }
14910 }
14911 }
14912 return %LocalProblems;
14913}
14914
14915sub tNameLock($$)
14916{
14917 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014918 my $Changed = 0;
14919 if(differentDumps("G"))
14920 { # different GCC versions
14921 $Changed = 1;
14922 }
14923 elsif(differentDumps("V"))
14924 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014925 if(not checkDump(1, "2.20")
14926 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014927 { # latest names update
14928 # 2.6: added restrict qualifier
14929 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014930 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014931 $Changed = 1;
14932 }
14933 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014934
14935 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14936 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14937
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014938 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14939 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14940
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014941 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014942 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014943 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014944 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014945 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014946 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014947 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014948 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014949 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014950 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014951 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14952 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14953 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954 { # equal base types
14955 return 0;
14956 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014957
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014958 if(not checkDump(1, "2.13")
14959 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014960 { # broken array names in ABI dumps < 2.13
14961 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014962 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014963 return 0;
14964 }
14965 }
14966
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014967 if(not checkDump(1, "2.6")
14968 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014969 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014970 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014971 and $TN2=~/\brestrict\b/) {
14972 return 0;
14973 }
14974 }
14975
14976 if(not checkDump(1, "2.20")
14977 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014978 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014979 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14980 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014981 return 0;
14982 }
14983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014985 else
14986 {
14987 # typedef struct {...} type_t
14988 # typedef struct type_t {...} type_t
14989 if(index($TN1, " ".$TN2)!=-1)
14990 {
14991 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14992 return 0;
14993 }
14994 }
14995 if(index($TN2, " ".$TN1)!=-1)
14996 {
14997 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14998 return 0;
14999 }
15000 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015001
15002 if($TT1 eq "FuncPtr"
15003 and $TT2 eq "FuncPtr")
15004 {
15005 my $TN1_C = $TN1;
15006 my $TN2_C = $TN2;
15007
15008 $TN1_C=~s/\b(struct|union) //g;
15009 $TN2_C=~s/\b(struct|union) //g;
15010
15011 if($TN1_C eq $TN2_C) {
15012 return 0;
15013 }
15014 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015015 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015016
15017 my ($N1, $N2) = ($TN1, $TN2);
15018 $N1=~s/\b(struct|union) //g;
15019 $N2=~s/\b(struct|union) //g;
15020
15021 if($N1 eq $N2)
15022 { # QList<struct QUrl> and QList<QUrl>
15023 return 0;
15024 }
15025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015026 return 1;
15027}
15028
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015029sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015030{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015031 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015032 if(defined $Cache{"differentDumps"}{$Check}) {
15033 return $Cache{"differentDumps"}{$Check};
15034 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015035 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015036 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015037 if($Check eq "G")
15038 {
15039 if(getGccVersion(1) ne getGccVersion(2))
15040 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015041 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015042 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015043 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015044 if($Check eq "V")
15045 {
15046 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15047 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15048 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015049 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015050 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015052 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015053 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015054}
15055
15056sub formatVersion($$)
15057{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015058 my ($V, $Digits) = @_;
15059 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015060 return join(".", splice(@Elems, 0, $Digits));
15061}
15062
15063sub htmlSpecChars($)
15064{
15065 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015066 if(not $Str) {
15067 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015069 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15070 $Str=~s/</&lt;/g;
15071 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15072 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015073 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15074 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015075 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015076 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015077 $Str=~s/\n/<br\/>/g;
15078 $Str=~s/\"/&quot;/g;
15079 $Str=~s/\'/&#39;/g;
15080 return $Str;
15081}
15082
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015083sub xmlSpecChars($)
15084{
15085 my $Str = $_[0];
15086 if(not $Str) {
15087 return $Str;
15088 }
15089
15090 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15091 $Str=~s/</&lt;/g;
15092 $Str=~s/>/&gt;/g;
15093
15094 $Str=~s/\"/&quot;/g;
15095 $Str=~s/\'/&#39;/g;
15096
15097 return $Str;
15098}
15099
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015100sub xmlSpecChars_R($)
15101{
15102 my $Str = $_[0];
15103 if(not $Str) {
15104 return $Str;
15105 }
15106
15107 $Str=~s/&amp;/&/g;
15108 $Str=~s/&lt;/</g;
15109 $Str=~s/&gt;/>/g;
15110
15111 $Str=~s/&quot;/"/g;
15112 $Str=~s/&#39;/'/g;
15113
15114 return $Str;
15115}
15116
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015117sub black_name($)
15118{
15119 my $Name = $_[0];
15120 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15121}
15122
15123sub highLight_Signature($)
15124{
15125 my $Signature = $_[0];
15126 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15127}
15128
15129sub highLight_Signature_Italic_Color($)
15130{
15131 my $Signature = $_[0];
15132 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15133}
15134
15135sub separate_symbol($)
15136{
15137 my $Symbol = $_[0];
15138 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15139 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15140 ($Name, $Spec, $Ver) = ($1, $2, $3);
15141 }
15142 return ($Name, $Spec, $Ver);
15143}
15144
15145sub cut_f_attrs($)
15146{
15147 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15148 return $2;
15149 }
15150 return "";
15151}
15152
15153sub highLight_Signature_PPos_Italic($$$$$)
15154{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015155 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15156 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15158 my $Return = "";
15159 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15160 $Return = $2;
15161 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015162 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015164 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015165 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015166 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015167 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015168 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015169 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015170 }
15171 return $Signature;
15172 }
15173 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15174 $Begin.=" " if($Begin!~/ \Z/);
15175 $End = cut_f_attrs($Signature);
15176 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015177 my ($Short, $Params) = split_Signature($Signature);
15178 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015179 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015180 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015181 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015182 $Part=~s/\A\s+|\s+\Z//g;
15183 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15184 if($Part=~/\([\*]+(\w+)\)/i) {
15185 $ParamName = $1;#func-ptr
15186 }
15187 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15188 $ParamName = $1;
15189 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015190 if(not $ParamName)
15191 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015192 push(@Parts, $Part_Styled);
15193 next;
15194 }
15195 if($ItalicParams and not $TName_Tid{1}{$Part}
15196 and not $TName_Tid{2}{$Part})
15197 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015198 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015199 if($Param_Pos ne ""
15200 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015201 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202 }
15203 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015204 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015206 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015207 }
15208 $Part_Styled=~s/,(\w)/, $1/g;
15209 push(@Parts, $Part_Styled);
15210 }
15211 if(@Parts)
15212 {
15213 foreach my $Num (0 .. $#Parts)
15214 {
15215 if($Num==$#Parts)
15216 { # add ")" to the last parameter
15217 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15218 }
15219 elsif(length($Parts[$Num])<=45) {
15220 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15221 }
15222 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015223 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224 }
15225 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015226 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015227 }
15228 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015229 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015230 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015231 $Signature=~s!\[\]![&#160;]!g;
15232 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015233 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15234 if($SymbolVersion) {
15235 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15236 }
15237 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015238}
15239
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015240sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015241{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015242 my $Signature = $_[0];
15243 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15244 {
15245 $Signature=~s/\A\Q$ShortName\E\(//g;
15246 cut_f_attrs($Signature);
15247 $Signature=~s/\)\Z//;
15248 return ($ShortName, $Signature);
15249 }
15250
15251 # error
15252 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253}
15254
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015255sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015256{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015257 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015258 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015259 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15260 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015261 foreach my $Pos (0 .. length($Params) - 1)
15262 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015263 my $S = substr($Params, $Pos, 1);
15264 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015265 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015266 }
15267 if($S eq "," and
15268 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015269 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015270 if($Comma)
15271 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015272 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015273 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015274 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015275 }
15276 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015277 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015278 }
15279 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015280 if(not $Sp)
15281 { # remove spaces
15282 foreach (@Parts)
15283 {
15284 s/\A //g;
15285 s/ \Z//g;
15286 }
15287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288 return @Parts;
15289}
15290
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015291sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015292{
15293 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015294 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015295 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015296 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15297 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298 $Center+=length($1);
15299 }
15300 foreach my $Pos (0 .. length($Sign)-1)
15301 {
15302 my $S = substr($Sign, $Pos, 1);
15303 if($S eq $Target)
15304 {
15305 if($B{"("}==$B{")"}
15306 and $B{"<"}==$B{">"}) {
15307 return $Center;
15308 }
15309 }
15310 if(defined $B{$S}) {
15311 $B{$S}+=1;
15312 }
15313 $Center+=1;
15314 }
15315 return 0;
15316}
15317
15318sub appendFile($$)
15319{
15320 my ($Path, $Content) = @_;
15321 return if(not $Path);
15322 if(my $Dir = get_dirname($Path)) {
15323 mkpath($Dir);
15324 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015325 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015326 print FILE $Content;
15327 close(FILE);
15328}
15329
15330sub writeFile($$)
15331{
15332 my ($Path, $Content) = @_;
15333 return if(not $Path);
15334 if(my $Dir = get_dirname($Path)) {
15335 mkpath($Dir);
15336 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015337 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015338 print FILE $Content;
15339 close(FILE);
15340}
15341
15342sub readFile($)
15343{
15344 my $Path = $_[0];
15345 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015346 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015347 local $/ = undef;
15348 my $Content = <FILE>;
15349 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015350 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015351 $Content=~s/\r/\n/g;
15352 }
15353 return $Content;
15354}
15355
15356sub get_filename($)
15357{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015358 if(defined $Cache{"get_filename"}{$_[0]}) {
15359 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015360 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015361 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15362 return ($Cache{"get_filename"}{$_[0]}=$1);
15363 }
15364 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015365}
15366
15367sub get_dirname($)
15368{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015369 if(defined $Cache{"get_dirname"}{$_[0]}) {
15370 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015371 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015372 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15373 return ($Cache{"get_dirname"}{$_[0]}=$1);
15374 }
15375 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015376}
15377
15378sub separate_path($) {
15379 return (get_dirname($_[0]), get_filename($_[0]));
15380}
15381
15382sub esc($)
15383{
15384 my $Str = $_[0];
15385 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15386 return $Str;
15387}
15388
15389sub readLineNum($$)
15390{
15391 my ($Path, $Num) = @_;
15392 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015393 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015394 foreach (1 ... $Num) {
15395 <FILE>;
15396 }
15397 my $Line = <FILE>;
15398 close(FILE);
15399 return $Line;
15400}
15401
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015402sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015404 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015405 return () if(not $Path or not -f $Path);
15406 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015407 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15408 {
15409 foreach my $AttrVal (split(/;/, $1))
15410 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015411 if($AttrVal=~/(.+):(.+)/)
15412 {
15413 my ($Name, $Value) = ($1, $2);
15414 $Attributes{$Name} = $Value;
15415 }
15416 }
15417 }
15418 return \%Attributes;
15419}
15420
15421sub is_abs($) {
15422 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15423}
15424
15425sub get_abs_path($)
15426{ # abs_path() should NOT be called for absolute inputs
15427 # because it can change them
15428 my $Path = $_[0];
15429 if(not is_abs($Path)) {
15430 $Path = abs_path($Path);
15431 }
15432 return $Path;
15433}
15434
15435sub get_OSgroup()
15436{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015437 my $N = $Config{"osname"};
15438 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015439 return "macos";
15440 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015441 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015442 return "bsd";
15443 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015444 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015445 return "beos";
15446 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015447 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015448 return "symbian";
15449 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015450 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015451 return "windows";
15452 }
15453 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015454 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015455 }
15456}
15457
15458sub getGccVersion($)
15459{
15460 my $LibVersion = $_[0];
15461 if($GCC_VERSION{$LibVersion})
15462 { # dump version
15463 return $GCC_VERSION{$LibVersion};
15464 }
15465 elsif($UsedDump{$LibVersion}{"V"})
15466 { # old-version dumps
15467 return "unknown";
15468 }
15469 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15470 if(not $GccVersion) {
15471 return "unknown";
15472 }
15473 return $GccVersion;
15474}
15475
15476sub showArch($)
15477{
15478 my $Arch = $_[0];
15479 if($Arch eq "arm"
15480 or $Arch eq "mips") {
15481 return uc($Arch);
15482 }
15483 return $Arch;
15484}
15485
15486sub getArch($)
15487{
15488 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015489
15490 if($TargetArch) {
15491 return $TargetArch;
15492 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015493 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015494 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015495 return $CPU_ARCH{$LibVersion};
15496 }
15497 elsif($UsedDump{$LibVersion}{"V"})
15498 { # old-version dumps
15499 return "unknown";
15500 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015501
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015502 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015503}
15504
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015505sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015506{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015507 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015509 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015510 if(getArch(1) ne getArch(2)
15511 or getArch(1) eq "unknown"
15512 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015513 { # don't show architecture in the header
15514 $ArchInfo="";
15515 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015516 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015517 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015518 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015519 }
15520 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015521 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015522 }
15523 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015524 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015525 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015526
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015527 my $V1 = $Descriptor{1}{"Version"};
15528 my $V2 = $Descriptor{2}{"Version"};
15529
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015530 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15531 {
15532 my $M1 = $UsedDump{1}{"M"};
15533 my $M2 = $UsedDump{2}{"M"};
15534
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015535 my $M1S = $M1;
15536 my $M2S = $M2;
15537
15538 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15539 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15540
15541 if($M1S eq $M2S
15542 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015543 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015544 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15545 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015546 }
15547 else
15548 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015549 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15550 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015551 }
15552 }
15553 else
15554 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015555 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015556 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015557 }
15558
15559 $Title .= $ArchInfo;
15560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015561 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015562 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015563 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015564 $Title = "<h1>".$Title."</h1>\n";
15565 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015566}
15567
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015568sub get_CheckedHeaders($)
15569{
15570 my $LibVersion = $_[0];
15571
15572 my @Headers = ();
15573
15574 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15575 {
15576 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015577
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015578 if(not is_target_header($File, $LibVersion)) {
15579 next;
15580 }
15581
15582 if(skipHeader($File, $LibVersion)) {
15583 next;
15584 }
15585
15586 push(@Headers, $Path);
15587 }
15588
15589 return @Headers;
15590}
15591
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015592sub get_SourceInfo()
15593{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015594 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015595
15596 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015597 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015598 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15599 $CheckedHeaders .= "<div class='h_list'>\n";
15600 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 +040015601 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015602 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15603 my $Name = get_filename($Identity);
15604 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15605 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015606 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015607 $CheckedHeaders .= "</div>\n";
15608 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015609 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015610
15611 if(my @Sources = keys(%{$Registered_Sources{1}}))
15612 {
15613 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15614 $CheckedSources .= "<div class='h_list'>\n";
15615 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15616 {
15617 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15618 my $Name = get_filename($Identity);
15619 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15620 $CheckedSources .= $Name.$Comment."<br/>\n";
15621 }
15622 $CheckedSources .= "</div>\n";
15623 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15624 }
15625
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015626 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015628 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015629 $CheckedLibs .= "<div class='lib_list'>\n";
15630 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15631 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015632 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015633 $CheckedLibs .= $Library."<br/>\n";
15634 }
15635 $CheckedLibs .= "</div>\n";
15636 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015637 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015638
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015639 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15640}
15641
15642sub get_ObjTitle()
15643{
15644 if(defined $UsedDump{1}{"DWARF"}) {
15645 return "Objects";
15646 }
15647 else {
15648 return ucfirst($SLIB_TYPE)." Libraries";
15649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015650}
15651
15652sub get_TypeProblems_Count($$$)
15653{
15654 my ($TypeChanges, $TargetPriority, $Level) = @_;
15655 my $Type_Problems_Count = 0;
15656 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15657 {
15658 my %Kinds_Target = ();
15659 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15660 {
15661 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15662 {
15663 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015664 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15665 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015666 if($Kinds_Target{$Kind}{$Target}) {
15667 next;
15668 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015669
15670 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15671 {
15672 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15673 { # select a problem with the highest priority
15674 next;
15675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015676 }
15677 $Kinds_Target{$Kind}{$Target} = 1;
15678 $Type_Problems_Count += 1;
15679 }
15680 }
15681 }
15682 return $Type_Problems_Count;
15683}
15684
15685sub get_Summary($)
15686{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015687 my $Level = $_[0];
15688 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015689 $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 +040015690 %{$RESULT{$Level}} = (
15691 "Problems"=>0,
15692 "Warnings"=>0,
15693 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015694 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015695 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015696 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015697 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015698 {
15699 if(not defined $CompatRules{$Level}{$Kind})
15700 { # unknown rule
15701 if(not $UnknownRules{$Level}{$Kind})
15702 { # only one warning
15703 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15704 $UnknownRules{$Level}{$Kind}=1;
15705 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015706 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015707 }
15708 }
15709 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015710 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15711 {
15712 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15713 {
15714 if(not defined $CompatRules{$Level}{$Kind})
15715 { # unknown rule
15716 if(not $UnknownRules{$Level}{$Kind})
15717 { # only one warning
15718 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15719 $UnknownRules{$Level}{$Kind}=1;
15720 }
15721 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15722 }
15723 }
15724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015725 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015726 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015727 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015728 {
15729 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15730 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015731 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015732 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015733 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015734 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 $Added += 1;
15736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015737 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 {
15739 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015740 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015741 }
15742 else
15743 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015744 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015745 $I_Other += 1;
15746 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015747 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015748 $I_Problems_High += 1;
15749 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015750 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015751 $I_Problems_Medium += 1;
15752 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015753 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015754 $I_Problems_Low += 1;
15755 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015756 if(($Severity ne "Low" or $StrictCompat)
15757 and $Severity ne "Safe") {
15758 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015759 }
15760 }
15761 }
15762 }
15763 }
15764 }
15765 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015766 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015767 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015768 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 {
15770 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15771 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015772 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015773 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015774 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15775 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015776 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015777 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15778
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015779 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 { # select a problem with the highest priority
15781 next;
15782 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015783
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015784 if(($Severity ne "Low" or $StrictCompat)
15785 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015786 {
15787 if(defined $TotalAffected{$Level}{$Interface})
15788 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015789 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15790 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015791 }
15792 }
15793 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015794 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015796 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015797
15798 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15799
15800 if($MaxSeverity)
15801 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015802 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15803 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015804 }
15805 }
15806 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015807 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015809 }
15810 }
15811 }
15812 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015813
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015814 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15815 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15816 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15817 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015818
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015819 %TypeChanges = (); # free memory
15820
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015821 # changed and removed public symbols
15822 my $SCount = keys(%{$CheckedSymbols{$Level}});
15823 if($ExtendedCheck)
15824 { # don't count external_func_0 for constants
15825 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015827 if($SCount)
15828 {
15829 my %Weight = (
15830 "High" => 100,
15831 "Medium" => 50,
15832 "Low" => 25
15833 );
15834 foreach (keys(%{$TotalAffected{$Level}})) {
15835 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015836 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015837 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015838 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015839 else {
15840 $RESULT{$Level}{"Affected"} = 0;
15841 }
15842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015843 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15844 if($RESULT{$Level}{"Affected"}>=100) {
15845 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015846 }
15847
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015848 $RESULT{$Level}{"Problems"} += $Removed;
15849 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015850 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015851 if($StrictCompat) {
15852 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15853 }
15854 else {
15855 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015857
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015858 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015859 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015860 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015861 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015862 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015863 if($Severity eq "Safe")
15864 {
15865 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015866 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015867 elsif($Severity eq "Low")
15868 {
15869 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015871 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015872 }
15873
15874 if($C_Problems_Low)
15875 {
15876 if($StrictCompat) {
15877 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15878 }
15879 else {
15880 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 }
15882 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015883 if($RESULT{$Level}{"Problems"}
15884 and $RESULT{$Level}{"Affected"}) {
15885 $RESULT{$Level}{"Verdict"} = "incompatible";
15886 }
15887 else {
15888 $RESULT{$Level}{"Verdict"} = "compatible";
15889 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015890
15891 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15892 if(not $TotalTypes)
15893 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015894 $TotalTypes = keys(%{$TName_Tid{1}});
15895 }
15896
15897 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15898 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15899
15900 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15901
15902 if($ReportFormat eq "xml")
15903 { # XML
15904 # test info
15905 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15906 $TestInfo .= " <version1>\n";
15907 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015908 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015909 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15910 $TestInfo .= " </version1>\n";
15911
15912 $TestInfo .= " <version2>\n";
15913 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015914 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15916 $TestInfo .= " </version2>\n";
15917 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15918
15919 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015920 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015921 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015922 $TestResults .= " <headers>\n";
15923 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15924 {
15925 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15926 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15927 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15928 }
15929 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015930 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015931
15932 if(my @Sources = keys(%{$Registered_Sources{1}}))
15933 {
15934 $TestResults .= " <sources>\n";
15935 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15936 {
15937 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15938 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15939 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15940 }
15941 $TestResults .= " </sources>\n";
15942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015943
15944 $TestResults .= " <libs>\n";
15945 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15946 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015947 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015948 $TestResults .= " <name>$Library</name>\n";
15949 }
15950 $TestResults .= " </libs>\n";
15951
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015952 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015953 $TestResults .= " <types>".$TotalTypes."</types>\n";
15954
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015955 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15956 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015957 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15958
15959 # problem summary
15960 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15961 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15962
15963 $Problem_Summary .= " <problems_with_types>\n";
15964 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15965 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15966 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15967 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15968 $Problem_Summary .= " </problems_with_types>\n";
15969
15970 $Problem_Summary .= " <problems_with_symbols>\n";
15971 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15972 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15973 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015974 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015975 $Problem_Summary .= " </problems_with_symbols>\n";
15976
15977 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015978 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015981 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15982
15983 return ($TestInfo.$TestResults.$Problem_Summary, "");
15984 }
15985 else
15986 { # HTML
15987 # test info
15988 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015989 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015990
15991 if($TargetComponent eq "library") {
15992 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
15993 }
15994 else {
15995 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
15996 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015997
15998 my (@VInf1, @VInf2, $AddTestInfo) = ();
15999 if($Arch1 ne "unknown"
16000 and $Arch2 ne "unknown")
16001 { # CPU arch
16002 if($Arch1 eq $Arch2)
16003 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016004 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016005 }
16006 else
16007 { # go to the version number
16008 push(@VInf1, showArch($Arch1));
16009 push(@VInf2, showArch($Arch2));
16010 }
16011 }
16012 if($GccV1 ne "unknown"
16013 and $GccV2 ne "unknown"
16014 and $OStarget ne "windows")
16015 { # GCC version
16016 if($GccV1 eq $GccV2)
16017 { # go to the separate section
16018 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16019 }
16020 else
16021 { # go to the version number
16022 push(@VInf1, "gcc ".$GccV1);
16023 push(@VInf2, "gcc ".$GccV2);
16024 }
16025 }
16026 # show long version names with GCC version and CPU architecture name (if different)
16027 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16028 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16029 $TestInfo .= $AddTestInfo;
16030 #if($COMMON_LANGUAGE{1}) {
16031 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16032 #}
16033 if($ExtendedCheck) {
16034 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16035 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016036 if($JoinReport)
16037 {
16038 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016039 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016040 }
16041 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016042 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016043 }
16044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016045 $TestInfo .= "</table>\n";
16046
16047 # test results
16048 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016049 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016050
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016051 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016052 {
16053 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16054 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16055 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016056
16057 if(my @Sources = keys(%{$Registered_Sources{1}}))
16058 {
16059 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16060 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016062
16063 if(not $ExtendedCheck)
16064 {
16065 my $Libs_Link = "0";
16066 $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 +040016067 $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 +040016068 }
16069
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016070 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016071
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016072 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016073 if($JoinReport) {
16074 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16075 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016076 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016077 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016078 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16079 }
16080 else {
16081 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16082 }
16083 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016084 $TestResults .= "</table>\n";
16085
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016086 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016087 # problem summary
16088 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016089 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016090 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16091
16092 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016093 if($Added>0)
16094 {
16095 if($JoinReport) {
16096 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16097 }
16098 else {
16099 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16100 }
16101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016102 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016103 $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 +040016104
16105 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016106 if($Removed>0)
16107 {
16108 if($JoinReport) {
16109 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16110 }
16111 else {
16112 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16113 }
16114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016115 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016116 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16117 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016118
16119 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016120 $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 +040016121 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016122 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16123 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016124
16125 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016126 $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 +040016127 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016128 $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 +040016129
16130 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016131 $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 +040016132 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016133 $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 +040016134
16135 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016136 $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 +040016137 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016138 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16139 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016140
16141 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016142 $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 +040016143 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016144 $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 +040016145
16146 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016147 $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 +040016148 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016149 $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 +040016150
16151 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016152 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16153 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016154 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016155 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016156 $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 +040016157
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016158 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016159 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016160 {
16161 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016162 $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 +030016163 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016164 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016165
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016166 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016167 {
16168 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016169 $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 +030016170 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016172
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016173 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016174 {
16175 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16176 $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 +030016177 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016178 }
16179
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016180 $META_DATA .= "tool_version:$TOOL_VERSION";
16181 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016182 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016183 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16184 }
16185}
16186
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016187sub getStyle($$$)
16188{
16189 my ($Subj, $Act, $Num) = @_;
16190 my %Style = (
16191 "A"=>"new",
16192 "R"=>"failed",
16193 "S"=>"passed",
16194 "L"=>"warning",
16195 "M"=>"failed",
16196 "H"=>"failed"
16197 );
16198 if($Num>0) {
16199 return " class='".$Style{$Act}."'";
16200 }
16201 return "";
16202}
16203
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016204sub show_number($)
16205{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016206 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016207 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016208 my $Num = cut_off_number($_[0], 2, 0);
16209 if($Num eq "0")
16210 {
16211 foreach my $P (3 .. 7)
16212 {
16213 $Num = cut_off_number($_[0], $P, 1);
16214 if($Num ne "0") {
16215 last;
16216 }
16217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016218 }
16219 if($Num eq "0") {
16220 $Num = $_[0];
16221 }
16222 return $Num;
16223 }
16224 return $_[0];
16225}
16226
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016227sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016228{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016229 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230 if($num!~/\./)
16231 {
16232 $num .= ".";
16233 foreach (1 .. $digs_to_cut-1) {
16234 $num .= "0";
16235 }
16236 }
16237 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16238 {
16239 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16240 $num .= "0";
16241 }
16242 }
16243 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16244 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16245 }
16246 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 if($z) {
16248 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016250 return $num;
16251}
16252
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016253sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016254{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016255 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016256 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016257
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016258 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016259 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16260 {
16261 my $Header = $Constants{1}{$Constant}{"Header"};
16262 if(not $Header)
16263 { # added
16264 $Header = $Constants{2}{$Constant}{"Header"}
16265 }
16266
16267 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16268 {
16269 if(not defined $CompatRules{$Level}{$Kind}) {
16270 next;
16271 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016272 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016273 next;
16274 }
16275 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016277 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016278
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 if($ReportFormat eq "xml")
16280 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016281 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016282 {
16283 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016284 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016285 {
16286 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016287 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16288 {
16289 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16290 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16291 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016292
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016293 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16294 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16295 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016296 if($Overcome) {
16297 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16298 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016299 $CHANGED_CONSTANTS .= " </problem>\n";
16300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016301 $CHANGED_CONSTANTS .= " </constant>\n";
16302 }
16303 $CHANGED_CONSTANTS .= " </header>\n";
16304 }
16305 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16306 }
16307 else
16308 { # HTML
16309 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016310 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311 {
16312 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016313 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016314 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016315 my $Report = "";
16316
16317 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16318 {
16319 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16320 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016321 $Report .= "<tr>\n<th>1</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>$Effect</td>\n</tr>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016322 $Number += 1;
16323 }
16324 if($Report)
16325 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016326 $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 Ponomarenko8f4b9812013-02-07 19:11:42 +040016327 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16328 $Report = insertIDs($Report);
16329 }
16330 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016331 }
16332 $CHANGED_CONSTANTS .= "<br/>\n";
16333 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016334 if($CHANGED_CONSTANTS)
16335 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016336 my $Title = "Problems with Constants, $TargetSeverity Severity";
16337 if($TargetSeverity eq "Safe")
16338 { # Safe Changes
16339 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016340 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016341 $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 +040016342 }
16343 }
16344 return $CHANGED_CONSTANTS;
16345}
16346
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016347sub getTitle($$$)
16348{
16349 my ($Header, $Library, $NameSpace) = @_;
16350 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016351
16352 # if($Library and $Library!~/\.\w+\Z/) {
16353 # $Library .= " (.$LIB_EXT)";
16354 # }
16355
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016356 if($Header and $Library)
16357 {
16358 $Title .= "<span class='h_name'>$Header</span>";
16359 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16360 }
16361 elsif($Library) {
16362 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16363 }
16364 elsif($Header) {
16365 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16366 }
16367 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016368 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016369 }
16370 return $Title;
16371}
16372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016373sub get_Report_Added($)
16374{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016375 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016376 my $ADDED_INTERFACES = "";
16377 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016378 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016379 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016380 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016381 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016382 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 {
16384 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16385 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016386 if($Level eq "Source" and $ReportFormat eq "html")
16387 { # do not show library name in HTML report
16388 $DyLib = "";
16389 }
16390 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016391 }
16392 }
16393 }
16394 if($ReportFormat eq "xml")
16395 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016396 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 {
16398 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016399 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016400 {
16401 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016402 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016403 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16404 }
16405 $ADDED_INTERFACES .= " </library>\n";
16406 }
16407 $ADDED_INTERFACES .= " </header>\n";
16408 }
16409 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16410 }
16411 else
16412 { # HTML
16413 my $Added_Number = 0;
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 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016416 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016417 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016418 my %NameSpaceSymbols = ();
16419 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016420 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016422 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016423 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016424 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16425 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016426 foreach my $Interface (@SortedInterfaces)
16427 {
16428 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016429 my $Signature = get_Signature($Interface, 2);
16430 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016431 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016433 if($Interface=~/\A(_Z|\?)/)
16434 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016436 $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 +040016437 }
16438 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016439 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016440 }
16441 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016442 else
16443 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016445 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016446 }
16447 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016448 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016449 }
16450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016451 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016452 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016454 }
16455 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016456 if($ADDED_INTERFACES)
16457 {
16458 my $Anchor = "<a name='Added'></a>";
16459 if($JoinReport) {
16460 $Anchor = "<a name='".$Level."_Added'></a>";
16461 }
16462 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016463 }
16464 }
16465 return $ADDED_INTERFACES;
16466}
16467
16468sub get_Report_Removed($)
16469{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016470 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016471 my $REMOVED_INTERFACES = "";
16472 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016473 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016474 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016475 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016477 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016479 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16480 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016481 if($Level eq "Source" and $ReportFormat eq "html")
16482 { # do not show library name in HTML report
16483 $DyLib = "";
16484 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016485 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016486 }
16487 }
16488 }
16489 if($ReportFormat eq "xml")
16490 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016491 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016492 {
16493 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016494 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016495 {
16496 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016497 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16498 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016499 }
16500 $REMOVED_INTERFACES .= " </library>\n";
16501 }
16502 $REMOVED_INTERFACES .= " </header>\n";
16503 }
16504 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16505 }
16506 else
16507 { # HTML
16508 my $Removed_Number = 0;
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 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016511 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016512 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016513 my %NameSpaceSymbols = ();
16514 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016515 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016516 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016517 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016519 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16520 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016521 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016522 {
16523 $Removed_Number += 1;
16524 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016525 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016527 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016528 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016529 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016530 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016531 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016532 $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 +040016533 }
16534 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016535 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016536 }
16537 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016538 else
16539 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016541 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542 }
16543 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016544 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016545 }
16546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016547 }
16548 }
16549 $REMOVED_INTERFACES .= "<br/>\n";
16550 }
16551 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016552 if($REMOVED_INTERFACES)
16553 {
16554 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16555 if($JoinReport) {
16556 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16557 }
16558 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016559 }
16560 }
16561 return $REMOVED_INTERFACES;
16562}
16563
16564sub getXmlParams($$)
16565{
16566 my ($Content, $Problem) = @_;
16567 return "" if(not $Content or not $Problem);
16568 my %XMLparams = ();
16569 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16570 {
16571 my $Macro = "\@".lc($Attr);
16572 if($Content=~/\Q$Macro\E/) {
16573 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16574 }
16575 }
16576 my @PString = ();
16577 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016578 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016579 }
16580 if(@PString) {
16581 return " ".join(" ", @PString);
16582 }
16583 else {
16584 return "";
16585 }
16586}
16587
16588sub addMarkup($)
16589{
16590 my $Content = $_[0];
16591 # auto-markup
16592 $Content=~s/\n[ ]*//; # spaces
16593 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16594 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016595 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16597 if($Content=~/\ANOTE:/)
16598 { # notes
16599 $Content=~s!(NOTE):!<b>$1</b>:!g;
16600 }
16601 else {
16602 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16603 }
16604 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16605 my @Keywords = (
16606 "void",
16607 "const",
16608 "static",
16609 "restrict",
16610 "volatile",
16611 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016612 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016613 );
16614 my $MKeys = join("|", @Keywords);
16615 foreach (@Keywords) {
16616 $MKeys .= "|non-".$_;
16617 }
16618 $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 +040016619
16620 # Markdown
16621 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16622 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016623 return $Content;
16624}
16625
16626sub applyMacroses($$$$)
16627{
16628 my ($Level, $Kind, $Content, $Problem) = @_;
16629 return "" if(not $Content or not $Problem);
16630 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16631 $Content = addMarkup($Content);
16632 # macros
16633 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16634 {
16635 my $Macro = "\@".lc($Attr);
16636 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016637 if(not defined $Value
16638 or $Value eq "") {
16639 next;
16640 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016641
16642 if(index($Content, $Macro)==-1) {
16643 next;
16644 }
16645
16646 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16647 and $Kind!~/_Type_/
16648 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016649 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016651 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016652 $Value = black_name($Value);
16653 }
16654 elsif($Value=~/\s/) {
16655 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16656 }
16657 elsif($Value=~/\A\d+\Z/
16658 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16659 { # bits to bytes
16660 if($Value % $BYTE_SIZE)
16661 { # bits
16662 if($Value==1) {
16663 $Value = "<b>".$Value."</b> bit";
16664 }
16665 else {
16666 $Value = "<b>".$Value."</b> bits";
16667 }
16668 }
16669 else
16670 { # bytes
16671 $Value /= $BYTE_SIZE;
16672 if($Value==1) {
16673 $Value = "<b>".$Value."</b> byte";
16674 }
16675 else {
16676 $Value = "<b>".$Value."</b> bytes";
16677 }
16678 }
16679 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016680 else
16681 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 $Value = "<b>".htmlSpecChars($Value)."</b>";
16683 }
16684 $Content=~s/\Q$Macro\E/$Value/g;
16685 }
16686
16687 if($Content=~/(\A|[^\@\w])\@\w/)
16688 {
16689 if(not $IncompleteRules{$Level}{$Kind})
16690 { # only one warning
16691 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16692 $IncompleteRules{$Level}{$Kind} = 1;
16693 }
16694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016695 return $Content;
16696}
16697
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016698sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016700 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016701 my $INTERFACE_PROBLEMS = "";
16702 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016703
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016704 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016705 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016706 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16707 if($SV and defined $CompatProblems{$Level}{$SN}) {
16708 next;
16709 }
16710 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016711 {
16712 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016713 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016715 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16716 my $DyLib = $Symbol_Library{1}{$Symbol};
16717 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016718 { # Symbol with Version
16719 $DyLib = $Symbol_Library{1}{$VSym};
16720 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016721 if(not $DyLib)
16722 { # const global data
16723 $DyLib = "";
16724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016725 if($Level eq "Source" and $ReportFormat eq "html")
16726 { # do not show library name in HTML report
16727 $DyLib = "";
16728 }
16729 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16730 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016731 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016732 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16733 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016734 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016735 }
16736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016737 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16738 {
16739 delete($SymbolChanges{$Symbol}{$Kind});
16740 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016741 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016742 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016743 }
16744 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016745 if(not keys(%{$SymbolChanges{$Symbol}})) {
16746 delete($SymbolChanges{$Symbol});
16747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016749
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016750 if($ReportFormat eq "xml")
16751 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 {
16754 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016755 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016756 {
16757 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016758 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16759 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016760 {
16761 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16762 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16763 {
16764 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16765 {
16766 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016767 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016769 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16770 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16771 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16772 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16773 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016774 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16775 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016777 $INTERFACE_PROBLEMS .= " </problem>\n";
16778 }
16779 }
16780 $INTERFACE_PROBLEMS .= " </symbol>\n";
16781 }
16782 $INTERFACE_PROBLEMS .= " </library>\n";
16783 }
16784 $INTERFACE_PROBLEMS .= " </header>\n";
16785 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016786 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016787 }
16788 else
16789 { # HTML
16790 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016791 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016792 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016793 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016795 my (%NameSpaceSymbols, %NewSignature) = ();
16796 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016797 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016798 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016799 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016800 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016801 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016802 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 +040016803 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016804 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016805 my $Signature = get_Signature($Symbol, 1);
16806 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016808 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016809 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016812 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016813 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016815 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016816 }
16817 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16818 {
16819 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016820 $SYMBOL_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>".$Effect."</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 $ProblemNum += 1;
16822 $ProblemsNum += 1;
16823 }
16824 }
16825 }
16826 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016829 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016831 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016832 }
16833 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016834 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016836 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16837 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16838 if($NewSignature{$Symbol})
16839 { # argument list changed to
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016840 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span>\n<br/>\n<span class='new_sign'>".highLight_Signature_Italic_Color($NewSignature{$Symbol})."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016842 if($Symbol=~/\A(_Z|\?)/) {
16843 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16844 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016845 $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 +040016846 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016847 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016848 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016849 }
16850 }
16851 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016852 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016853 }
16854 }
16855 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016856
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016857 if($INTERFACE_PROBLEMS)
16858 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016859 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16860 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16861 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 { # Safe Changes
16863 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016864 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016865 $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 +040016866 }
16867 }
16868 return $INTERFACE_PROBLEMS;
16869}
16870
16871sub get_Report_TypeProblems($$)
16872{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016874 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016875 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016876
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016877 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016880 {
16881 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16882 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016883 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016885 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016886 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016887 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016888
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016889 if($Severity eq "Safe"
16890 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016891 next;
16892 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016893
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016894 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16895 {
16896 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16897 { # select a problem with the highest priority
16898 next;
16899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016901
16902 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903 }
16904 }
16905 }
16906 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016907
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016908 my %Kinds_Locations = ();
16909 foreach my $TypeName (keys(%TypeChanges))
16910 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016911 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16913 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016914 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016915 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016916 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016917 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016918 { # other priority
16919 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16920 next;
16921 }
16922 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16923 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016924 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016925 { # duplicate target
16926 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16927 next;
16928 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016929 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016930 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016931 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 }
16933 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16934 delete($TypeChanges{$TypeName}{$Kind});
16935 }
16936 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016937 if(not keys(%{$TypeChanges{$TypeName}})) {
16938 delete($TypeChanges{$TypeName});
16939 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016941
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016942 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 +040016943 if($ReportFormat eq "xml")
16944 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016945 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946 {
16947 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016948 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016949 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016950 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016951 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16952 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016953 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 {
16955 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16956 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16957 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16958 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16959 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16960 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016961 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16962 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 $TYPE_PROBLEMS .= " </problem>\n";
16965 }
16966 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016967 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016968 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 $TYPE_PROBLEMS .= showVTables($TypeName);
16970 }
16971 $TYPE_PROBLEMS .= " </type>\n";
16972 }
16973 $TYPE_PROBLEMS .= " </header>\n";
16974 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016975 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016976 }
16977 else
16978 { # HTML
16979 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 my (%NameSpace_Type) = ();
16983 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016984 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 }
16986 foreach my $NameSpace (sort keys(%NameSpace_Type))
16987 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016988 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016989 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 +040016990 foreach my $TypeName (@SortedTypes)
16991 {
16992 my $ProblemNum = 1;
16993 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016995 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16996 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016997 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016998 {
16999 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17000 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17001 {
17002 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017003 $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>$Effect</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 $ProblemNum += 1;
17005 $ProblemsNum += 1;
17006 }
17007 }
17008 }
17009 $ProblemNum -= 1;
17010 if($TYPE_REPORT)
17011 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017012 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017013 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017014 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017015 $ShowVTables = showVTables($TypeName);
17016 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017017
17018 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017019 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17020 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17021 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17022 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017023 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017024 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 }
17026 }
17027 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017028 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017029 }
17030 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 if($TYPE_PROBLEMS)
17033 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017034 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17035 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017036 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017037 { # Safe Changes
17038 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017039 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017040 $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 +040017041 }
17042 }
17043 return $TYPE_PROBLEMS;
17044}
17045
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017046sub show_Type($$$)
17047{
17048 my ($Name, $Html, $LibVersion) = @_;
17049 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17050 $TType = lc($TType);
17051 if($TType=~/struct|union|enum/) {
17052 $Name=~s/\A\Q$TType\E //g;
17053 }
17054 if($Html) {
17055 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17056 }
17057 else {
17058 $Name = $TType." ".$Name;
17059 }
17060 return $Name;
17061}
17062
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017063sub get_Anchor($$$)
17064{
17065 my ($Kind, $Level, $Severity) = @_;
17066 if($JoinReport)
17067 {
17068 if($Severity eq "Safe") {
17069 return "Other_".$Level."_Changes_In_".$Kind."s";
17070 }
17071 else {
17072 return $Kind."_".$Level."_Problems_".$Severity;
17073 }
17074 }
17075 else
17076 {
17077 if($Severity eq "Safe") {
17078 return "Other_Changes_In_".$Kind."s";
17079 }
17080 else {
17081 return $Kind."_Problems_".$Severity;
17082 }
17083 }
17084}
17085
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017086sub showVTables($)
17087{
17088 my $TypeName = $_[0];
17089 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017090 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 if(defined $Type1{"VTable"}
17092 and keys(%{$Type1{"VTable"}}))
17093 {
17094 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017095 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017096 if(defined $Type2{"VTable"}
17097 and keys(%{$Type2{"VTable"}}))
17098 {
17099 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17100 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017101 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017102 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017103 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17104 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 }
17106 my $VTABLES = "";
17107 if($ReportFormat eq "xml")
17108 { # XML
17109 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017110 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017112 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017113 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17114 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017115 $VTABLES .= " </entry>\n";
17116 }
17117 $VTABLES .= " </vtable>\n\n";
17118 }
17119 else
17120 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017121 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017122 $VTABLES .= "<tr><th>Offset</th>";
17123 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017124 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017125 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 {
17127 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017128
17129 my $E1 = $Entries{$Index}{"E1"};
17130 my $E2 = $Entries{$Index}{"E2"};
17131
17132 if($E1 ne $E2
17133 and $E1!~/ 0x/
17134 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017136 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017137 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017138 $Color1 = " class='failed'";
17139 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017140 }
17141 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017142 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 }
17144 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017145 $VTABLES .= "<tr><th>".$Index."</th>\n";
17146 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17147 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 }
17149 $VTABLES .= "</table><br/>\n";
17150 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017151 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017152 }
17153 return $VTABLES;
17154 }
17155 }
17156 return "";
17157}
17158
17159sub simpleVEntry($)
17160{
17161 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017162 if(not defined $VEntry
17163 or $VEntry eq "") {
17164 return "";
17165 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017166
17167 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017168 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17169 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17170 if($VEntry=~/\A_ZThn.+\Z/) {
17171 $VEntry = "non-virtual thunk";
17172 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017173 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017174 # support for old GCC versions
17175 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17176 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17177 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17179 return $VEntry;
17180}
17181
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017182sub adjustParamPos($$$)
17183{
17184 my ($Pos, $Symbol, $LibVersion) = @_;
17185 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17186 {
17187 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17188 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17189 {
17190 return $Pos-1;
17191 }
17192
17193 return $Pos;
17194 }
17195
17196 return undef;
17197}
17198
17199sub getParamPos($$$)
17200{
17201 my ($Name, $Symbol, $LibVersion) = @_;
17202
17203 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17204 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17205 {
17206 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17207 foreach (keys(%{$Info->{"Param"}}))
17208 {
17209 if($Info->{"Param"}{$_}{"name"} eq $Name)
17210 {
17211 return $_;
17212 }
17213 }
17214 }
17215
17216 return undef;
17217}
17218
17219sub getParamName($)
17220{
17221 my $Loc = $_[0];
17222 $Loc=~s/\->.*//g;
17223 return $Loc;
17224}
17225
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017226sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017227{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017228 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017229 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017230
17231 if(defined $AffectLimit)
17232 {
17233 $LIMIT = $AffectLimit;
17234 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017235
17236 my %SymSel = ();
17237 my %SymLocKind = ();
17238
17239 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017240 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017241 if(index($Symbol, "_Z")==0
17242 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017243 { # duplicated problems for C2 constructors, D2 and D0 destructors
17244 next;
17245 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017246
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017247 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017248 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017249 if(not defined $CompatProblems{$Level}{$Symbol}
17250 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17251 next;
17252 }
17253
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017254 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017255 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017256 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257 next;
17258 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017259
17260 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17261 if($Level eq "Source")
17262 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017263 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017264 }
17265
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017266 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017267 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017268 { # duplicated problems for versioned symbols
17269 next;
17270 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017271
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017272 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017273 if($Type_Name ne $Target_TypeName) {
17274 next;
17275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017276
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017277 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017278 }
17279 }
17280 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017281
17282 foreach my $Symbol (sort keys(%SymLocKind))
17283 {
17284 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17285 {
17286 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17287 {
17288 $SymSel{$Symbol}{"Loc"} = $Loc;
17289 $SymSel{$Symbol}{"Kind"} = $Kind;
17290
17291 last LOOP;
17292 }
17293 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017294 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017297 my $Num = 0;
17298
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017299 if($ReportFormat eq "xml")
17300 { # XML
17301 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017302
17303 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017304 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017305 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017306 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017307 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017309 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017310 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017311 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017312 $Target .= " param=\"$PName\"";
17313 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017314 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017315 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017316 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017317 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017318 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017319 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017320 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017321
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017322 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017323 $Target .= " field=\"$1\"";
17324 }
17325
17326 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017327 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017328 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017329
17330 if($Num>$LIMIT) {
17331 last LOOP;
17332 }
17333
17334 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017335 }
17336 $Affected .= " </affected>\n";
17337 }
17338 else
17339 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017340 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017341 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017342 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17343 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017344 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017345 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17346
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017347 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017348 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17349
17350 if($Num>$LIMIT) {
17351 last;
17352 }
17353
17354 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017355 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017356
17357 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017358 $Affected .= " ...\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017360
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017361 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362 if($Affected)
17363 {
17364 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017365 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017366 }
17367 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 return $Affected;
17370}
17371
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017372sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017373{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017374 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017375 if($L2=~/\A(retval|this)\b/
17376 and $L1!~/\A(retval|this)\b/)
17377 {
17378 if($L1!~/\-\>/) {
17379 return 1;
17380 }
17381 elsif($L2=~/\-\>/) {
17382 return 1;
17383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017384 }
17385 return 0;
17386}
17387
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017388sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017389{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017390 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017391
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017392 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017393
17394 my $Location_I = $Location;
17395 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017397 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017398
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017399 if($Kind eq "Overridden_Virtual_Method"
17400 or $Kind eq "Overridden_Virtual_Method_B") {
17401 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17402 }
17403 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17404 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017405 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17406
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017407 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17408 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017409 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17410 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 if($ClassName eq $Problem{"Type_Name"}) {
17413 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17414 }
17415 else {
17416 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17417 }
17418 }
17419 else
17420 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017421 my $TypeID = undef;
17422
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017423 if($Location=~/retval/)
17424 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017425 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017426 push(@Sentence, "Field \'".$Location."\' in return value");
17427 }
17428 else {
17429 push(@Sentence, "Return value");
17430 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017431
17432 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017433 }
17434 elsif($Location=~/this/)
17435 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017436 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017437 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17438 }
17439 else {
17440 push(@Sentence, "\'this\' pointer");
17441 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017442
17443 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017444 }
17445 else
17446 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017447
17448 my $PName = getParamName($Location);
17449 my $PPos = getParamPos($PName, $Symbol, 1);
17450
17451 if(index($Location, "->")!=-1) {
17452 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017453 }
17454 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017455 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017456 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017457 if($PName) {
17458 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017459 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017460
17461 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17462 }
17463
17464 if($Location!~/this/)
17465 {
17466 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017467 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017468 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017469 push(@Sentence, "(pointer)");
17470 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017471 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017472 push(@Sentence, "(reference)");
17473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474 }
17475 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017477 if($Location eq "this") {
17478 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17479 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017480 else
17481 {
17482 my $Location_T = $Location;
17483 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17484
17485 my $TypeID_Problem = $TypeID;
17486 if($Location_T) {
17487 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17488 }
17489
17490 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17491 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17492 }
17493 else {
17494 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17495 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017496 }
17497 }
17498 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017499 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017500 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 +040017501 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017502
17503 my $Sent = join(" ", @Sentence);
17504
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017505 $Sent=~s/->/./g;
17506
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017507 if($ReportFormat eq "xml")
17508 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017509 $Sent=~s/'//g;
17510 }
17511
17512 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017513}
17514
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017515sub getFieldType($$$)
17516{
17517 my ($Location, $TypeId, $LibVersion) = @_;
17518
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017519 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017520
17521 foreach my $Name (@Fields)
17522 {
17523 my %Info = get_BaseType($TypeId, $LibVersion);
17524
17525 foreach my $Pos (keys(%{$Info{"Memb"}}))
17526 {
17527 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17528 {
17529 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17530 last;
17531 }
17532 }
17533 }
17534
17535 return $TypeId;
17536}
17537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017538sub get_XmlSign($$)
17539{
17540 my ($Symbol, $LibVersion) = @_;
17541 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17542 my $Report = "";
17543 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17544 {
17545 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017546 my $Type = $Info->{"Param"}{$Pos}{"type"};
17547 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017548 foreach my $Typedef (keys(%ChangedTypedef))
17549 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017550 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17551 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017553 }
17554 $Report .= " <param pos=\"$Pos\">\n";
17555 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017556 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017557 $Report .= " </param>\n";
17558 }
17559 if(my $Return = $Info->{"Return"})
17560 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017561 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017562 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017563 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017564 $Report .= " </retval>\n";
17565 }
17566 return $Report;
17567}
17568
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017569sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017570{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017571 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017572 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017573 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017575 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17576 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017577 next;
17578 }
17579 $Report .= " <symbol name=\"$Symbol\">\n";
17580 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017581 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017582 {
17583 if(defined $CompleteSignature{1}{$Symbol}
17584 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17585 {
17586 $P1 = get_XmlSign($Symbol, 1);
17587 $S1 = get_Signature($Symbol, 1);
17588 }
17589 elsif($Symbol=~/\A(_Z|\?)/) {
17590 $S1 = $tr_name{$Symbol};
17591 }
17592 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017593 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017594 {
17595 if(defined $CompleteSignature{2}{$Symbol}
17596 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17597 {
17598 $P2 = get_XmlSign($Symbol, 2);
17599 $S2 = get_Signature($Symbol, 2);
17600 }
17601 elsif($Symbol=~/\A(_Z|\?)/) {
17602 $S2 = $tr_name{$Symbol};
17603 }
17604 }
17605 if($S1)
17606 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017607 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017608 $Report .= $P1;
17609 $Report .= " </old>\n";
17610 }
17611 if($S2 and $S2 ne $S1)
17612 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017613 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017614 $Report .= $P2;
17615 $Report .= " </new>\n";
17616 }
17617 $Report .= " </symbol>\n";
17618 }
17619 $Report .= "</symbols_info>\n";
17620 return $Report;
17621}
17622
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017623sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017624{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017625 my ($Level, $Report) = @_;
17626 if($ReportFormat eq "xml") {
17627 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017628 }
17629 if($StdOut)
17630 { # --stdout option
17631 print STDOUT $Report;
17632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017633 else
17634 {
17635 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017636 mkpath(get_dirname($RPath));
17637
17638 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17639 print REPORT $Report;
17640 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017641 }
17642}
17643
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017644sub getReport($)
17645{
17646 my $Level = $_[0];
17647 if($ReportFormat eq "xml")
17648 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017649 if($Level eq "Join")
17650 {
17651 my $Report = "<reports>\n";
17652 $Report .= getReport("Binary");
17653 $Report .= getReport("Source");
17654 $Report .= "</reports>\n";
17655 return $Report;
17656 }
17657 else
17658 {
17659 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17660 my ($Summary, $MetaData) = get_Summary($Level);
17661 $Report .= $Summary."\n";
17662 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17663 $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 +040017664
17665 # additional symbols info (if needed)
17666 # $Report .= get_Report_SymbolsInfo($Level);
17667
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017668 $Report .= "</report>\n";
17669 return $Report;
17670 }
17671 }
17672 else
17673 { # HTML
17674 my $CssStyles = readModule("Styles", "Report.css");
17675 my $JScripts = readModule("Scripts", "Sections.js");
17676 if($Level eq "Join")
17677 {
17678 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17679 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017680 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017681 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17682 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 +040017683 my ($BSummary, $BMetaData) = get_Summary("Binary");
17684 my ($SSummary, $SMetaData) = get_Summary("Source");
17685 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 +030017686 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017687 <br/>
17688 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017689 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17690 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017691 </div>";
17692 $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>";
17693 $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 +030017694 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017695 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017696 return $Report;
17697 }
17698 else
17699 {
17700 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017701 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17702 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17703 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 +040017704 if($Level eq "Binary")
17705 {
17706 if(getArch(1) eq getArch(2)
17707 and getArch(1) ne "unknown") {
17708 $Description .= " on ".showArch(getArch(1));
17709 }
17710 }
17711 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 +030017712 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017713 $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);
17715 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017716 $Report .= "</div>\n<br/><br/><br/>\n";
17717 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017718 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017719 return $Report;
17720 }
17721 }
17722}
17723
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017724sub getLegend()
17725{
17726 return "<br/>
17727<table class='summary'>
17728<tr>
17729 <td class='new'>added</td>
17730 <td class='passed'>compatible</td>
17731</tr>
17732<tr>
17733 <td class='warning'>warning</td>
17734 <td class='failed'>incompatible</td>
17735</tr></table>\n";
17736}
17737
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017738sub createReport()
17739{
17740 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017741 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017742 writeReport("Join", getReport("Join"));
17743 }
17744 elsif($DoubleReport)
17745 { # default
17746 writeReport("Binary", getReport("Binary"));
17747 writeReport("Source", getReport("Source"));
17748 }
17749 elsif($BinaryOnly)
17750 { # --binary
17751 writeReport("Binary", getReport("Binary"));
17752 }
17753 elsif($SourceOnly)
17754 { # --source
17755 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017756 }
17757}
17758
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017759sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017760{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017761 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017762
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017763 $Footer .= "<hr/>\n";
17764 $Footer .= "<div class='footer' align='right'>";
17765 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17766 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017767 $Footer .= "<br/>\n";
17768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017769 return $Footer;
17770}
17771
17772sub get_Report_Problems($$)
17773{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017774 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017775
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017776 my $Report = get_Report_TypeProblems($Severity, $Level);
17777 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017778 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017779 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017780
17781 if($Severity eq "Low" or $Severity eq "Safe") {
17782 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017783 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017785 if($ReportFormat eq "html")
17786 {
17787 if($Report)
17788 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017789 if($JoinReport)
17790 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017791 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017792 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17793 }
17794 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017795 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017798 else
17799 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017800 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017801 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17802 }
17803 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017804 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017806 }
17807 }
17808 }
17809 return $Report;
17810}
17811
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017812sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017813{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017814 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17815 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17816 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17817 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017818 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17819 <meta name=\"keywords\" content=\"$Keywords\" />
17820 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017821 <title>
17822 $Title
17823 </title>
17824 <style type=\"text/css\">
17825 $Styles
17826 </style>
17827 <script type=\"text/javascript\" language=\"JavaScript\">
17828 <!--
17829 $Scripts
17830 -->
17831 </script>
17832 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017833}
17834
17835sub insertIDs($)
17836{
17837 my $Text = $_[0];
17838 while($Text=~/CONTENT_ID/)
17839 {
17840 if(int($Content_Counter)%2) {
17841 $ContentID -= 1;
17842 }
17843 $Text=~s/CONTENT_ID/c_$ContentID/;
17844 $ContentID += 1;
17845 $Content_Counter += 1;
17846 }
17847 return $Text;
17848}
17849
17850sub checkPreprocessedUnit($)
17851{
17852 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017853 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017854 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017855 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017856
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017857 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017858 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017859 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017860 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017861 chomp($Line);
17862 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017863 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017864 $CurHeader = path_format($1, $OSgroup);
17865 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017866 $CurClass = "";
17867
17868 if(index($CurHeader, $TMP_DIR)==0) {
17869 next;
17870 }
17871
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017872 if(substr($CurHeaderName, 0, 1) eq "<")
17873 { # <built-in>, <command-line>, etc.
17874 $CurHeaderName = "";
17875 $CurHeader = "";
17876 }
17877
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017878 if($ExtraInfo)
17879 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017880 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017881 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17882 }
17883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017884 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017885 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017886 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017887 if($CurHeaderName)
17888 {
17889 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17890 and not $Registered_Headers{$Version}{$CurHeader})
17891 { # not a target
17892 next;
17893 }
17894 if(not is_target_header($CurHeaderName, 1)
17895 and not is_target_header($CurHeaderName, 2))
17896 { # user-defined header
17897 next;
17898 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017899 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017900 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017901
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017902 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017903 {
17904 my ($Name, $Value) = ($1, $2);
17905 if(not $Constants{$Version}{$Name}{"Access"})
17906 {
17907 $Constants{$Version}{$Name}{"Access"} = "public";
17908 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017909 if($CurHeaderName) {
17910 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17911 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017912 }
17913 }
17914 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17915 $Constants{$Version}{$1}{"Access"} = "private";
17916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017917 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017918 else
17919 {
17920 if(defined $ExtraDump)
17921 {
17922 if($Line=~/(\w+)\s*\(/)
17923 { # functions
17924 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17925 }
17926 #elsif($Line=~/(\w+)\s*;/)
17927 #{ # data
17928 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17929 #}
17930 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17931 $CurClass = $2;
17932 }
17933 }
17934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017935 }
17936 close(PREPROC);
17937 foreach my $Constant (keys(%{$Constants{$Version}}))
17938 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017939 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17940 {
17941 delete($Constants{$Version}{$Constant});
17942 next;
17943 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017944 if(not $ExtraDump and ($Constant=~/_h\Z/i
17945 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017946 { # skip
17947 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017948 }
17949 else {
17950 delete($Constants{$Version}{$Constant}{"Access"});
17951 }
17952 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017953 if($Debug)
17954 {
17955 mkpath($DEBUG_PATH{$Version});
17956 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017958}
17959
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017960sub uncoverConstant($$)
17961{
17962 my ($LibVersion, $Constant) = @_;
17963 return "" if(not $LibVersion or not $Constant);
17964 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17965 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17966 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17967 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017968
17969 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017970 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017971 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17972 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017973 {
17974 push(@RecurConstant, $Constant);
17975 my $Uncovered = uncoverConstant($LibVersion, $Value);
17976 if($Uncovered ne "") {
17977 $Value = $Uncovered;
17978 }
17979 pop(@RecurConstant);
17980 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017981
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017982 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017983 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017984 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17985 }
17986 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17987}
17988
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017989sub simpleConstant($$)
17990{
17991 my ($LibVersion, $Value) = @_;
17992 if($Value=~/\W/)
17993 {
17994 my $Value_Copy = $Value;
17995 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17996 {
17997 my $Word = $1;
17998 if($Value!~/$Word\s*\(/)
17999 {
18000 my $Val = uncoverConstant($LibVersion, $Word);
18001 if($Val ne "")
18002 {
18003 $Value=~s/\b$Word\b/$Val/g;
18004 }
18005 }
18006 }
18007 }
18008 return $Value;
18009}
18010
18011sub computeValue($)
18012{
18013 my $Value = $_[0];
18014
18015 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18016 return $1;
18017 }
18018
18019 if($Value=~/\A[\d\-\+()]+\Z/) {
18020 return eval($Value);
18021 }
18022
18023 return $Value;
18024}
18025
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018026my %IgnoreConstant = map {$_=>1} (
18027 "VERSION",
18028 "VERSIONCODE",
18029 "VERNUM",
18030 "VERS_INFO",
18031 "PATCHLEVEL",
18032 "INSTALLPREFIX",
18033 "VBUILD",
18034 "VPATCH",
18035 "VMINOR",
18036 "BUILD_STRING",
18037 "BUILD_TIME",
18038 "PACKAGE_STRING",
18039 "PRODUCTION",
18040 "CONFIGURE_COMMAND",
18041 "INSTALLDIR",
18042 "BINDIR",
18043 "CONFIG_FILE_PATH",
18044 "DATADIR",
18045 "EXTENSION_DIR",
18046 "INCLUDE_PATH",
18047 "LIBDIR",
18048 "LOCALSTATEDIR",
18049 "SBINDIR",
18050 "SYSCONFDIR",
18051 "RELEASE",
18052 "SOURCE_ID",
18053 "SUBMINOR",
18054 "MINOR",
18055 "MINNOR",
18056 "MINORVERSION",
18057 "MAJOR",
18058 "MAJORVERSION",
18059 "MICRO",
18060 "MICROVERSION",
18061 "BINARY_AGE",
18062 "INTERFACE_AGE",
18063 "CORE_ABI",
18064 "PATCH",
18065 "COPYRIGHT",
18066 "TIMESTAMP",
18067 "REVISION",
18068 "PACKAGE_TAG",
18069 "PACKAGEDATE",
18070 "NUMVERSION",
18071 "Release",
18072 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018073);
18074
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018075sub constantFilter($$$)
18076{
18077 my ($Name, $Value, $Level) = @_;
18078
18079 if($Level eq "Binary")
18080 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018081 if($Name=~/_t\Z/)
18082 { # __malloc_ptr_t
18083 return 1;
18084 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018085 foreach (keys(%IgnoreConstant))
18086 {
18087 if($Name=~/(\A|_)$_(_|\Z)/)
18088 { # version
18089 return 1;
18090 }
18091 if(/\A[A-Z].*[a-z]\Z/)
18092 {
18093 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18094 { # version
18095 return 1;
18096 }
18097 }
18098 }
18099 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18100 { # version
18101 return 1;
18102 }
18103 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18104 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18105 return 1;
18106 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018107
18108 if($Value=~/\A["'].*['"]/i)
18109 { # string
18110 return 0;
18111 }
18112
18113 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18114 { # static int gcry_pth_init
18115 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018116 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018117 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018118 return 1;
18119 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018120 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018121 { # foo(p)
18122 return 1;
18123 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018124 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018125 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018126 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018127 return 1;
18128 }
18129 }
18130
18131 return 0;
18132}
18133
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018134sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018135{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018136 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018137 foreach my $Constant (keys(%{$Constants{1}}))
18138 {
18139 if($SkipConstants{1}{$Constant})
18140 { # skipped by the user
18141 next;
18142 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018143
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018144 if(my $Header = $Constants{1}{$Constant}{"Header"})
18145 {
18146 if(not is_target_header($Header, 1)
18147 and not is_target_header($Header, 2))
18148 { # user-defined header
18149 next;
18150 }
18151 }
18152 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018153 next;
18154 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018155
18156 my $Old_Value = uncoverConstant(1, $Constant);
18157
18158 if(constantFilter($Constant, $Old_Value, $Level))
18159 { # separate binary and source problems
18160 next;
18161 }
18162
18163 if(not defined $Constants{2}{$Constant}{"Value"})
18164 { # removed
18165 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18166 "Target"=>$Constant,
18167 "Old_Value"=>$Old_Value );
18168 next;
18169 }
18170
18171 if($Constants{2}{$Constant}{"Value"} eq "")
18172 { # empty value
18173 # TODO: implement a rule
18174 next;
18175 }
18176
18177 my $New_Value = uncoverConstant(2, $Constant);
18178
18179 my $Old_Value_Pure = $Old_Value;
18180 my $New_Value_Pure = $New_Value;
18181
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018182 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18183 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18184 $New_Value_Pure=~s/(\W)\s+/$1/g;
18185 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018186
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018187 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018189 if($New_Value_Pure ne $Old_Value_Pure)
18190 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018191 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18192 { # complex values
18193 next;
18194 }
18195 if(computeValue($Old_Value) eq computeValue($New_Value))
18196 { # expressions
18197 next;
18198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018199 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18200 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18201 next;
18202 }
18203 if($Old_Value eq "0" and $New_Value eq "NULL")
18204 { # 0 => NULL
18205 next;
18206 }
18207 if($Old_Value eq "NULL" and $New_Value eq "0")
18208 { # NULL => 0
18209 next;
18210 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018211 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018212 "Target"=>$Constant,
18213 "Old_Value"=>$Old_Value,
18214 "New_Value"=>$New_Value );
18215 }
18216 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018217
18218 foreach my $Constant (keys(%{$Constants{2}}))
18219 {
18220 if(not defined $Constants{1}{$Constant}{"Value"})
18221 {
18222 if($SkipConstants{2}{$Constant})
18223 { # skipped by the user
18224 next;
18225 }
18226
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018227 if(my $Header = $Constants{2}{$Constant}{"Header"})
18228 {
18229 if(not is_target_header($Header, 1)
18230 and not is_target_header($Header, 2))
18231 { # user-defined header
18232 next;
18233 }
18234 }
18235 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018236 next;
18237 }
18238
18239 my $New_Value = uncoverConstant(2, $Constant);
18240 if(not defined $New_Value or $New_Value eq "") {
18241 next;
18242 }
18243
18244 if(constantFilter($Constant, $New_Value, $Level))
18245 { # separate binary and source problems
18246 next;
18247 }
18248
18249 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18250 "Target"=>$Constant,
18251 "New_Value"=>$New_Value );
18252 }
18253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018254}
18255
18256sub convert_integer($)
18257{
18258 my $Value = $_[0];
18259 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018260 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018261 return hex($Value);
18262 }
18263 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018264 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018265 return oct($Value);
18266 }
18267 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018268 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018269 return oct($Value);
18270 }
18271 else {
18272 return $Value;
18273 }
18274}
18275
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018276sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018277{
18278 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018279 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018280 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018281 {
18282 if($LibVersion==1)
18283 {
18284 printMsg("WARNING", "checking headers only");
18285 $CheckHeadersOnly = 1;
18286 }
18287 else {
18288 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18289 }
18290 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018291
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018292 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018293 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018294 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018295
18296 if($CheckUndefined)
18297 {
18298 my %UndefinedLibs = ();
18299
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018300 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18301
18302 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018303 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018304 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018305 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018306 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018307 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018308 if($Symbol_Library{$LibVersion}{$Symbol}
18309 or $DepSymbol_Library{$LibVersion}{$Symbol})
18310 { # exported by target library
18311 next;
18312 }
18313 if(index($Symbol, '@')!=-1)
18314 { # exported default symbol version (@@)
18315 $Symbol=~s/\@/\@\@/;
18316 if($Symbol_Library{$LibVersion}{$Symbol}
18317 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18318 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018319 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018320 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018321 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18322 $UndefinedLibs{$Path} = 1;
18323 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018324 }
18325 }
18326 }
18327 if($ExtraInfo)
18328 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018329 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018330 {
18331 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018332 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018333 foreach (@Paths)
18334 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018335 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018336 my ($Dir, $Name) = separate_path($_);
18337
18338 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018339 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018340 }
18341
18342 $Name = parse_libname($Name, "name", $OStarget);
18343 $Name=~s/\Alib//;
18344
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018345 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018346 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018347
18348 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18349 {
18350 $LibString = " -L".esc($Dir).$LibString;
18351 }
18352
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018353 writeFile($ExtraInfo."/libs-string", $LibString);
18354 }
18355 }
18356 }
18357
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018358 if($ExtraInfo) {
18359 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18360 }
18361
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018362 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018363 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018364 if($#LibPaths!=-1)
18365 {
18366 if(not keys(%{$Symbol_Library{$LibVersion}}))
18367 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018368 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018369 printMsg("WARNING", "checking headers only");
18370 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018371 }
18372 }
18373 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018374
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018375 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018376 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018377}
18378
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018379my %Prefix_Lib_Map=(
18380 # symbols for autodetecting library dependencies (by prefix)
18381 "pthread_" => ["libpthread"],
18382 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18383 "cairo_" => ["libcairo"],
18384 "gtk_" => ["libgtk-x11-2.0"],
18385 "atk_" => ["libatk-1.0"],
18386 "gdk_" => ["libgdk-x11-2.0"],
18387 "gl" => ["libGL"],
18388 "glu" => ["libGLU"],
18389 "popt" => ["libpopt"],
18390 "Py" => ["libpython"],
18391 "jpeg_" => ["libjpeg"],
18392 "BZ2_" => ["libbz2"],
18393 "Fc" => ["libfontconfig"],
18394 "Xft" => ["libXft"],
18395 "SSL_" => ["libssl"],
18396 "sem_" => ["libpthread"],
18397 "snd_" => ["libasound"],
18398 "art_" => ["libart_lgpl_2"],
18399 "dbus_g" => ["libdbus-glib-1"],
18400 "GOMP_" => ["libgomp"],
18401 "omp_" => ["libgomp"],
18402 "cms" => ["liblcms"]
18403);
18404
18405my %Pattern_Lib_Map=(
18406 "SL[a-z]" => ["libslang"]
18407);
18408
18409my %Symbol_Lib_Map=(
18410 # symbols for autodetecting library dependencies (by name)
18411 "pow" => "libm",
18412 "fmod" => "libm",
18413 "sin" => "libm",
18414 "floor" => "libm",
18415 "cos" => "libm",
18416 "dlopen" => "libdl",
18417 "deflate" => "libz",
18418 "inflate" => "libz",
18419 "move_panel" => "libpanel",
18420 "XOpenDisplay" => "libX11",
18421 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018422 "clock_gettime" => "librt",
18423 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018424);
18425
18426sub find_SymbolLibs($$)
18427{
18428 my ($LibVersion, $Symbol) = @_;
18429
18430 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18431 { # debug symbols
18432 return ();
18433 }
18434
18435 my %Paths = ();
18436
18437 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18438 {
18439 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18440 $Paths{$Path} = 1;
18441 }
18442 }
18443
18444 if(my $SymbolPrefix = getPrefix($Symbol))
18445 {
18446 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18447 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18448 }
18449
18450 if(not keys(%Paths))
18451 {
18452 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18453 {
18454 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18455 {
18456 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18457 $Paths{$Path} = 1;
18458 }
18459 }
18460 }
18461 }
18462
18463 if(not keys(%Paths))
18464 {
18465 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18466 {
18467 if($Symbol=~/\A$Prefix/)
18468 {
18469 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18470 {
18471 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18472 $Paths{$Path} = 1;
18473 }
18474 }
18475 }
18476 }
18477 }
18478
18479 if(not keys(%Paths))
18480 {
18481 if($SymbolPrefix)
18482 { # try to find a library by symbol prefix
18483 if($SymbolPrefix eq "inotify" and
18484 index($Symbol, "\@GLIBC")!=-1)
18485 {
18486 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18487 $Paths{$Path} = 1;
18488 }
18489 }
18490 else
18491 {
18492 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18493 $Paths{$Path} = 1;
18494 }
18495 }
18496 }
18497 }
18498
18499 if(my @Paths = keys(%Paths)) {
18500 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18501 }
18502 }
18503 return keys(%Paths);
18504}
18505
18506sub get_LibPath_Prefix($$)
18507{
18508 my ($LibVersion, $Prefix) = @_;
18509
18510 $Prefix = lc($Prefix);
18511 $Prefix=~s/[_]+\Z//g;
18512
18513 foreach ("-2", "2", "-1", "1", "")
18514 { # libgnome-2.so
18515 # libxml2.so
18516 # libdbus-1.so
18517 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18518 return $Path;
18519 }
18520 }
18521 return "";
18522}
18523
18524sub getPrefix($)
18525{
18526 my $Str = $_[0];
18527 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18528 { # XmuValidArea: Xmu
18529 return $1;
18530 }
18531 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18532 { # snfReadFont: snf
18533 return $1;
18534 }
18535 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18536 { # XRRTimes: XRR
18537 return $1;
18538 }
18539 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18540 { # H5HF_delete: H5
18541 return $1;
18542 }
18543 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18544 { # alarm_event_add: alarm_
18545 return $1;
18546 }
18547 elsif($Str=~/\A(([a-z])\2{1,})/i)
18548 { # ffopen
18549 return $1;
18550 }
18551 return "";
18552}
18553
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018554sub getSymbolSize($$)
18555{ # size from the shared library
18556 my ($Symbol, $LibVersion) = @_;
18557 return 0 if(not $Symbol);
18558 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18559 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18560 {
18561 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18562 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18563 {
18564 if($Size<0) {
18565 return -$Size;
18566 }
18567 }
18568 }
18569 return 0;
18570}
18571
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018572sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018573{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18574 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018575 my ($Name, $Type) = @_;
18576
18577 # single
18578 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018579 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018580 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018581 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018582 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018583
18584 # double
18585 if($Name=~/$DEFAULT_STD_PARMS/)
18586 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018587 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018588 {
18589 my ($ShortName, $FuncParams) = split_Signature($Name);
18590
18591 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18592 {
18593 if(index($FParam, "<")!=-1)
18594 {
18595 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18596 my $FParam_N = canonifyName($FParam, "T");
18597 if($FParam_N ne $FParam) {
18598 $Name=~s/\Q$FParam\E/$FParam_N/g;
18599 }
18600 }
18601 }
18602 }
18603 elsif($Type eq "T")
18604 {
18605 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18606
18607 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018608 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018609 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018610 my $FParam = $TParams[0];
18611 foreach my $Pos (1 .. $#TParams)
18612 {
18613 my $TParam = $TParams[$Pos];
18614 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18615 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18616 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018617 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018618 }
18619 }
18620 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018621 if($Type eq "S") {
18622 return formatName($Name, "S");
18623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018624 return $Name;
18625}
18626
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018627sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018628{
18629 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018630 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018631 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018632 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018633 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018634 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018635 next if($tr_name{$Symbol});
18636 $Symbol=~s/[\@\$]+(.*)\Z//;
18637 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018638 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018639 elsif(index($Symbol, "?")==0)
18640 {
18641 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018642 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018643 }
18644 else
18645 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018646 $tr_name{$Symbol} = $Symbol;
18647 $mangled_name_gcc{$Symbol} = $Symbol;
18648 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018649 }
18650 }
18651 if($#MnglNames1 > -1)
18652 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018653 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018654 foreach my $MnglName (@MnglNames1)
18655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018656 if(my $Unmangled = pop(@UnmangledNames))
18657 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018658 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018659 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18660 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18661 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018662 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018663 and $tr_name{$MnglName}=~/vtable for (.+)/)
18664 { # bind class name and v-table symbol
18665 my $ClassName = $1;
18666 $ClassVTable{$ClassName} = $MnglName;
18667 $VTableClass{$MnglName} = $ClassName;
18668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018669 }
18670 }
18671 }
18672 if($#MnglNames2 > -1)
18673 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018674 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018675 foreach my $MnglName (@MnglNames2)
18676 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018677 if(my $Unmangled = pop(@UnmangledNames))
18678 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018679 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018680 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18681 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018682 }
18683 }
18684 return \%tr_name;
18685}
18686
18687sub link_symbol($$$)
18688{
18689 my ($Symbol, $RunWith, $Deps) = @_;
18690 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18691 return 1;
18692 }
18693 if($Deps eq "+Deps")
18694 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018695 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018696 return 1;
18697 }
18698 }
18699 return 0;
18700}
18701
18702sub link_symbol_internal($$$)
18703{
18704 my ($Symbol, $RunWith, $Where) = @_;
18705 return 0 if(not $Where or not $Symbol);
18706 if($Where->{$RunWith}{$Symbol})
18707 { # the exact match by symbol name
18708 return 1;
18709 }
18710 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18711 { # indirect symbol version, i.e.
18712 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018713 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018714 if($Where->{$RunWith}{$VSym}) {
18715 return 1;
18716 }
18717 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018718 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018719 if($Sym and $Ver)
18720 { # search for the symbol with the same version
18721 # or without version
18722 if($Where->{$RunWith}{$Sym})
18723 { # old: foo@v|foo@@v
18724 # new: foo
18725 return 1;
18726 }
18727 if($Where->{$RunWith}{$Sym."\@".$Ver})
18728 { # old: foo|foo@@v
18729 # new: foo@v
18730 return 1;
18731 }
18732 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18733 { # old: foo|foo@v
18734 # new: foo@@v
18735 return 1;
18736 }
18737 }
18738 return 0;
18739}
18740
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018741sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018742{
18743 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018744 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018745 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018746 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018747 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018748 my $NM = get_CmdPath("nm");
18749 if(not $NM) {
18750 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018751 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018752 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018753 while(<APP>)
18754 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018755 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018756 push(@Imported, $1);
18757 }
18758 }
18759 close(APP);
18760 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018761 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018762 {
18763 my $DumpBinCmd = get_CmdPath("dumpbin");
18764 if(not $DumpBinCmd) {
18765 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18766 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018767 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018768 while(<APP>)
18769 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018770 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18771 push(@Imported, $1);
18772 }
18773 }
18774 close(APP);
18775 }
18776 else
18777 {
18778 my $ReadelfCmd = get_CmdPath("readelf");
18779 if(not $ReadelfCmd) {
18780 exitStatus("Not_Found", "can't find \"readelf\"");
18781 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018782 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018783 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018784 while(<APP>)
18785 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018786 if(defined $symtab)
18787 { # do nothing with symtab
18788 if(index($_, "'.dynsym'")!=-1)
18789 { # dynamic table
18790 $symtab = undef;
18791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018792 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018793 elsif(index($_, "'.symtab'")!=-1)
18794 { # symbol table
18795 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018796 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018797 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018798 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018799 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18800 if($Ndx eq "UND")
18801 { # only imported symbols
18802 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018803 }
18804 }
18805 }
18806 close(APP);
18807 }
18808 return @Imported;
18809}
18810
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018811my %ELF_BIND = map {$_=>1} (
18812 "WEAK",
18813 "GLOBAL"
18814);
18815
18816my %ELF_TYPE = map {$_=>1} (
18817 "FUNC",
18818 "IFUNC",
18819 "OBJECT",
18820 "COMMON"
18821);
18822
18823my %ELF_VIS = map {$_=>1} (
18824 "DEFAULT",
18825 "PROTECTED"
18826);
18827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018828sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018829{ # read the line of 'readelf' output corresponding to the symbol
18830 my @Info = split(/\s+/, $_[0]);
18831 # Num: Value Size Type Bind Vis Ndx Name
18832 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018833 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 shift(@Info); # spaces
18835 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018836
18837 if($#Info==7)
18838 { # UND SYMBOL (N)
18839 if($Info[7]=~/\(\d+\)/) {
18840 pop(@Info);
18841 }
18842 }
18843
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018844 if($#Info!=6)
18845 { # other lines
18846 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018848 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018849 return () if(not defined $ELF_BIND{$Info[3]});
18850 return () if(not defined $ELF_VIS{$Info[4]});
18851 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18852 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18853 return ();
18854 }
18855 if($OStarget eq "symbian")
18856 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18857 if(index($Info[6], "_._.absent_export_")!=-1)
18858 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18859 return ();
18860 }
18861 $Info[6]=~s/\@.+//g; # remove version
18862 }
18863 if(index($Info[2], "0x") == 0)
18864 { # size == 0x3d158
18865 $Info[2] = hex($Info[2]);
18866 }
18867 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018868}
18869
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018870sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018871{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018872 my ($LibVersion, $Name) = @_;
18873 return "" if(not $LibVersion or not $Name);
18874 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18875 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018876 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018877 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18878}
18879
18880sub get_LibPath_I($$)
18881{
18882 my ($LibVersion, $Name) = @_;
18883 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018884 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018885 if(-f $Name)
18886 { # absolute path
18887 return $Name;
18888 }
18889 else
18890 { # broken
18891 return "";
18892 }
18893 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018894 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018895 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018896 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018897 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018898 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018899 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018900 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018901 }
18902 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18903 { # ldconfig default paths
18904 return $DefaultPath;
18905 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018906 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018907 { # search in default linker directories
18908 # and then in all system paths
18909 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018910 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018911 }
18912 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018913 if(not defined $Cache{"checkSystemFiles"}) {
18914 checkSystemFiles();
18915 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018916 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18917 return $AllObjects[0];
18918 }
18919 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18920 {
18921 if($ShortName ne $Name)
18922 { # FIXME: check this case
18923 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18924 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018925 }
18926 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018927 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018928 # can't find
18929 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018930}
18931
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018932sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018933{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018934 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18935 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018936
18937 my $Real_Path = realpath($Lib_Path);
18938
18939 if(not $Real_Path)
18940 { # broken link
18941 return ();
18942 }
18943
18944 my $Lib_Name = get_filename($Real_Path);
18945
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018946 if($ExtraInfo)
18947 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018948 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018949 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018950 }
18951
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018952 if($IsNeededLib)
18953 {
18954 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18955 return ();
18956 }
18957 }
18958 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018959 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018961 push(@RecurLib, $Lib_Name);
18962 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018963 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18964
18965 if(not $IsNeededLib)
18966 { # special cases: libstdc++ and libc
18967 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18968 {
18969 if($ShortName eq "libstdc++")
18970 { # libstdc++.so.6
18971 $STDCXX_TESTING = 1;
18972 }
18973 elsif($ShortName eq "libc")
18974 { # libc-2.11.3.so
18975 $GLIBC_TESTING = 1;
18976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018977 }
18978 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018979 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018980 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018981 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018982 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018983 mkpath(get_dirname($DebugPath));
18984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018985 if($OStarget eq "macos")
18986 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018987 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018988 if(not $NM) {
18989 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018990 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018991 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018992 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018993 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018994 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018995 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018996 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018997 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018998 else
18999 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019000 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019002 while(<LIB>)
19003 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019004 if($CheckUndefined)
19005 {
19006 if(not $IsNeededLib)
19007 {
19008 if(/ U _([\w\$]+)\s*\Z/)
19009 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019010 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019011 next;
19012 }
19013 }
19014 }
19015
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019016 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019017 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019018 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019019 if($IsNeededLib)
19020 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019021 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019022 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019023 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19024 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019026 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019027 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019028 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019029 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19030 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019031 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19032 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019033 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019034 setLanguage($LibVersion, "C++");
19035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019036 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019037 }
19038 }
19039 }
19040 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019041
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019042 if($Deps)
19043 {
19044 if($LIB_TYPE eq "dynamic")
19045 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019046
19047 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019048 if(not $OtoolCmd) {
19049 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019050 }
19051
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019052 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19053 while(<LIB>)
19054 {
19055 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19056 and $1 ne $Lib_Path) {
19057 $NeededLib{$1} = 1;
19058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019060 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019062 }
19063 }
19064 elsif($OStarget eq "windows")
19065 { # Windows *.dll, *.lib
19066 my $DumpBinCmd = get_CmdPath("dumpbin");
19067 if(not $DumpBinCmd) {
19068 exitStatus("Not_Found", "can't find \"dumpbin\"");
19069 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019070 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019071 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019072 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019073 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019074 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019075 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019076 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019077 else
19078 { # write to pipe
19079 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019081 while(<LIB>)
19082 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19083 # 1198 4AD SetThreadToken (forwarded to ...)
19084 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019085 # 1 0 00005B30 ??0?N = ... (with pdb)
19086 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019087 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019088 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019089 { # dynamic, static and forwarded symbols
19090 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019091 if($IsNeededLib)
19092 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019093 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019094 {
19095 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19096 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019098 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019099 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019100 {
19101 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19102 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019103 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19104 {
19105 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19106 setLanguage($LibVersion, "C++");
19107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019109 }
19110 }
19111 }
19112 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019113
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019114 if($Deps)
19115 {
19116 if($LIB_TYPE eq "dynamic")
19117 { # dependencies
19118 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19119 while(<LIB>)
19120 {
19121 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19122 and $1 ne $Lib_Path) {
19123 $NeededLib{path_format($1, $OSgroup)} = 1;
19124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019125 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019126 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019128 }
19129 }
19130 else
19131 { # Unix; *.so, *.a
19132 # Symbian: *.dso, *.lib
19133 my $ReadelfCmd = get_CmdPath("readelf");
19134 if(not $ReadelfCmd) {
19135 exitStatus("Not_Found", "can't find \"readelf\"");
19136 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019137 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019138 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019139 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019140 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019141 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019142 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019143 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019144 else
19145 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019146 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019147 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019148 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019149 while(<LIB>)
19150 {
19151 if($LIB_TYPE eq "dynamic")
19152 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019153 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019154 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019155 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019156 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019157 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019158 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019159 # do nothing with symtab
19160 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019161 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019162 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019163 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019164 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 next;
19166 }
19167 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019168 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019170 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019172 if($CheckUndefined)
19173 {
19174 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019175 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019176 }
19177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 next;
19179 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019180 if($Bind eq "WEAK")
19181 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019182 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019183 if($Weak eq "-Weak")
19184 { # skip WEAK symbols
19185 next;
19186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019187 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019188 my $Short = $Symbol;
19189 $Short=~s/\@.+//g;
19190 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019191 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019192 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19193 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019194 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019195 if($IsNeededLib)
19196 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019197 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019198 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019199 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19200 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019203 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019204 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019205 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19206 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19207 if($Vers)
19208 {
19209 if($LIB_EXT eq "so")
19210 { # value
19211 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19212 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019214 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019215 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19216 {
19217 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19218 setLanguage($LibVersion, "C++");
19219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019221 }
19222 }
19223 }
19224 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019225
19226 if($Deps and $LIB_TYPE eq "dynamic")
19227 { # dynamic library specifics
19228 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19229 open(LIB, $Cmd." |");
19230
19231 while(<LIB>)
19232 {
19233 if(/NEEDED.+\[([^\[\]]+)\]/)
19234 { # dependencies:
19235 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19236 $NeededLib{$1} = 1;
19237 }
19238 }
19239
19240 close(LIB);
19241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019243 if($Vers)
19244 {
19245 if(not $IsNeededLib and $LIB_EXT eq "so")
19246 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019247 my %Found = ();
19248
19249 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019250 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019252 next if(index($Symbol,"\@")==-1);
19253 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019255 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019256 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019257 if($Symbol_SameValue ne $Symbol
19258 and index($Symbol_SameValue,"\@")==-1)
19259 {
19260 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019261 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019262 last;
19263 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019264 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019265 }
19266 }
19267
19268 # default
19269 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19270 {
19271 next if(defined $Found{$Symbol});
19272 next if(index($Symbol,"\@\@")==-1);
19273
19274 if($Symbol=~/\A([^\@]*)\@\@/
19275 and not $SymVer{$LibVersion}{$1})
19276 {
19277 $SymVer{$LibVersion}{$1} = $Symbol;
19278 $Found{$Symbol} = 1;
19279 }
19280 }
19281
19282 # non-default
19283 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19284 {
19285 next if(defined $Found{$Symbol});
19286 next if(index($Symbol,"\@")==-1);
19287
19288 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19289 and not $SymVer{$LibVersion}{$1})
19290 {
19291 $SymVer{$LibVersion}{$1} = $Symbol;
19292 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019293 }
19294 }
19295 }
19296 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019297 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019298 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019299 foreach my $DyLib (sort keys(%NeededLib))
19300 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019301 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19302
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019303 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19304 {
19305 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19306 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19307 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019309 }
19310 }
19311 pop(@RecurLib);
19312 return $Library_Symbol{$LibVersion};
19313}
19314
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019315sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019316{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019317 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019318 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019319 return keys(%Prefixes);
19320}
19321
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019322sub get_prefixes_I($$)
19323{
19324 foreach my $P (@{$_[0]})
19325 {
19326 my @Parts = reverse(split(/[\/\\]+/, $P));
19327 my $Name = $Parts[0];
19328 foreach (1 .. $#Parts)
19329 {
19330 $_[1]->{$Name}{$P} = 1;
19331 last if($_>4 or $Parts[$_] eq "include");
19332 $Name = $Parts[$_].$SLASH.$Name;
19333 }
19334 }
19335}
19336
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019337sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019338{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019339 $Cache{"checkSystemFiles"} = 1;
19340
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019341 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019342
19343 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019344 {
19345 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019346
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019347 my @Files = cmd_find($DevelPath,"f");
19348 foreach my $Link (cmd_find($DevelPath,"l"))
19349 { # add symbolic links
19350 if(-f $Link) {
19351 push(@Files, $Link);
19352 }
19353 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019354
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019355 # search for headers in /usr/lib
19356 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19357 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19358 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019359
19360 # search for libraries in /usr/lib (including symbolic links)
19361 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19362 foreach my $Path (@Libs)
19363 {
19364 my $N = get_filename($Path);
19365 $SystemObjects{$N}{$Path} = 1;
19366 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019367 }
19368 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019369
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019370 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019371 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019372 next if(not -d $DevelPath);
19373 # search for all header files in the /usr/include
19374 # with or without extension (ncurses.h, QtCore, ...)
19375 push(@SysHeaders, cmd_find($DevelPath,"f"));
19376 foreach my $Link (cmd_find($DevelPath,"l"))
19377 { # add symbolic links
19378 if(-f $Link) {
19379 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019381 }
19382 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019383 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019384}
19385
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019386sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019387{
19388 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019389 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19391 {
19392 if(not -e $Dest) {
19393 exitStatus("Access_Error", "can't access \'$Dest\'");
19394 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019395 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019396 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19397 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019398 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019399 }
19400 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019401 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019402}
19403
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019404sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019405{
19406 my ($Path, $LibVersion) = @_;
19407 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019408 my $Name = get_filename($Path);
19409 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019410 return 1;
19411 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019412 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019413 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19414 return 1;
19415 }
19416 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19417 {
19418 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19419 return 1;
19420 }
19421 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019422 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019423 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019424 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019425 return 1;
19426 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019427 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019428 return 1;
19429 }
19430 }
19431 return 0;
19432}
19433
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019434sub specificHeader($$)
19435{
19436 my ($Header, $Spec) = @_;
19437 my $Name = get_filename($Header);
19438
19439 if($Spec eq "windows")
19440 {# MS Windows
19441 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19442 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19443 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19444 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19445 my @Dirs = (
19446 "win32",
19447 "win64",
19448 "win",
19449 "windows",
19450 "msvcrt"
19451 ); # /gsf-win32/
19452 if(my $DIRs = join("|", @Dirs)) {
19453 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19454 }
19455 }
19456 elsif($Spec eq "macos")
19457 { # Mac OS
19458 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19459 }
19460
19461 return 0;
19462}
19463
19464sub skipAlienHeader($)
19465{
19466 my $Path = $_[0];
19467 my $Name = get_filename($Path);
19468 my $Dir = get_dirname($Path);
19469
19470 if($Tolerance=~/2/)
19471 { # 2 - skip internal headers
19472 my @Terms = (
19473 "p",
19474 "priv",
19475 "int",
19476 "impl",
19477 "implementation",
19478 "internal",
19479 "private",
19480 "old",
19481 "compat",
19482 "debug",
19483 "test",
19484 "gen"
19485 );
19486
19487 my @Dirs = (
19488 "private",
19489 "priv",
19490 "port",
19491 "impl",
19492 "internal",
19493 "detail",
19494 "details",
19495 "old",
19496 "compat",
19497 "debug",
19498 "config",
19499 "compiler",
19500 "platform",
19501 "test"
19502 );
19503
19504 if(my $TERMs = join("|", @Terms)) {
19505 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19506 }
19507 if(my $DIRs = join("|", @Dirs)) {
19508 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19509 }
19510
19511 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19512 }
19513
19514 if($Tolerance=~/1/)
19515 { # 1 - skip non-Linux headers
19516 if($OSgroup ne "windows")
19517 {
19518 if(specificHeader($Path, "windows")) {
19519 return 1;
19520 }
19521 }
19522 if($OSgroup ne "macos")
19523 {
19524 if(specificHeader($Path, "macos")) {
19525 return 1;
19526 }
19527 }
19528 }
19529
19530 # valid
19531 return 0;
19532}
19533
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019534sub skipHeader($$)
19535{
19536 my ($Path, $LibVersion) = @_;
19537 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019538 if(defined $Cache{"skipHeader"}{$Path}) {
19539 return $Cache{"skipHeader"}{$Path};
19540 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019541 if(defined $Tolerance and $Tolerance=~/1|2/)
19542 { # --tolerant
19543 if(skipAlienHeader($Path)) {
19544 return ($Cache{"skipHeader"}{$Path} = 1);
19545 }
19546 }
19547 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19548 return 0;
19549 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019550 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19551}
19552
19553sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019554{ # returns:
19555 # 1 - if header should NOT be included and checked
19556 # 2 - if header should NOT be included, but should be checked
19557 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019558 my $Name = get_filename($Path);
19559 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019560 return $Kind;
19561 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019562 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19563 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019564 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019565 if(index($Path, $D)!=-1)
19566 {
19567 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19568 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019570 }
19571 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019572 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19573 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019574 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019575 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19576 {
19577 if($Name=~/$P/) {
19578 return $Kind;
19579 }
19580 if($P=~/[\/\\]/ and $Path=~/$P/) {
19581 return $Kind;
19582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019583 }
19584 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019586 return 0;
19587}
19588
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019589sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019590{
19591 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019592 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019593 { # system directory
19594 return;
19595 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019596 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019597 { # already registered
19598 return;
19599 }
19600 foreach my $Path (find_libs($Dir,"",1))
19601 {
19602 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019603 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019604 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019606 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19607}
19608
19609sub registerObject($$)
19610{
19611 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019612
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019613 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019614 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019615 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019616 {
19617 if(my $SONAME = getSONAME($Path)) {
19618 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19619 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019620 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019621 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19622 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019623 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019624
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019625 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019626 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019627 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019628 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019629 if($ObjArch ne getArch_GCC($LibVersion))
19630 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19631 $CheckedArch{$LibVersion} = 1;
19632 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 +040019633 }
19634 }
19635 }
19636}
19637
19638sub getArch_Object($)
19639{
19640 my $Path = $_[0];
19641
19642 my %MachineType = (
19643 "14C" => "x86",
19644 "8664" => "x86_64",
19645 "1C0" => "arm",
19646 "200" => "ia64"
19647 );
19648
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019649 my %ArchName = (
19650 "s390:31-bit" => "s390",
19651 "s390:64-bit" => "s390x",
19652 "powerpc:common" => "ppc32",
19653 "powerpc:common64" => "ppc64",
19654 "i386:x86-64" => "x86_64",
19655 "mips:3000" => "mips",
19656 "sparc:v8plus" => "sparcv9"
19657 );
19658
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019659 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019660 {
19661 my $DumpbinCmd = get_CmdPath("dumpbin");
19662 if(not $DumpbinCmd) {
19663 exitStatus("Not_Found", "can't find \"dumpbin\"");
19664 }
19665
19666 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19667 my $Out = `$Cmd`;
19668
19669 if($Out=~/(\w+)\smachine/)
19670 {
19671 if(my $Type = $MachineType{uc($1)})
19672 {
19673 return $Type;
19674 }
19675 }
19676 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019677 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019678 {
19679 my $ObjdumpCmd = get_CmdPath("objdump");
19680 if(not $ObjdumpCmd) {
19681 exitStatus("Not_Found", "can't find \"objdump\"");
19682 }
19683
19684 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019685
19686 if($OSgroup eq "windows") {
19687 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19688 }
19689 else {
19690 $Cmd = "LANG=$LOCALE ".$Cmd;
19691 }
19692 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019693
19694 if($Out=~/architecture:\s+([\w\-\:]+)/)
19695 {
19696 my $Arch = $1;
19697 if($Arch=~s/\:(.+)//)
19698 {
19699 my $Suffix = $1;
19700
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019701 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019702 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019703 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019704 }
19705 }
19706
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019707 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019708 $Arch = "x86";
19709 }
19710
19711 if($Arch eq "x86-64") {
19712 $Arch = "x86_64";
19713 }
19714
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019715 if($Arch eq "ia64-elf64") {
19716 $Arch = "ia64";
19717 }
19718
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019719 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019720 }
19721 }
19722 else
19723 { # macos, etc.
19724 # TODO
19725 }
19726
19727 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019728}
19729
19730sub getSONAME($)
19731{
19732 my $Path = $_[0];
19733 return if(not $Path);
19734 if(defined $Cache{"getSONAME"}{$Path}) {
19735 return $Cache{"getSONAME"}{$Path};
19736 }
19737 my $ObjdumpCmd = get_CmdPath("objdump");
19738 if(not $ObjdumpCmd) {
19739 exitStatus("Not_Found", "can't find \"objdump\"");
19740 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019741 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019742 if($OSgroup eq "windows") {
19743 $SonameCmd .= " | find \"SONAME\"";
19744 }
19745 else {
19746 $SonameCmd .= " | grep SONAME";
19747 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019748 if(my $SonameInfo = `$SonameCmd`)
19749 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019750 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19751 return ($Cache{"getSONAME"}{$Path} = $1);
19752 }
19753 }
19754 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019755}
19756
19757sub getSOPaths_Dest($$)
19758{
19759 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019760 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019761 return ();
19762 }
19763 if(-f $Dest)
19764 {
19765 if(not parse_libname($Dest, "name", $OStarget)) {
19766 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19767 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019768 registerObject($Dest, $LibVersion);
19769 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019770 return ($Dest);
19771 }
19772 elsif(-d $Dest)
19773 {
19774 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019775 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019776 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019777 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19778 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019779 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 { # all files and symlinks that match the name of a library
19781 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19782 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019783 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019784 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019785 }
19786 }
19787 }
19788 else
19789 { # search for all files and symlinks
19790 foreach my $Path (find_libs($Dest,"",""))
19791 {
19792 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019793 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019794 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019795 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019796 }
19797 if($OSgroup eq "macos")
19798 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019799 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019800 {
19801 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019802 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019803 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019804 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19805 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019806 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019807 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019808 }
19809 }
19810 }
19811 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019812 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019813 }
19814 else {
19815 return ();
19816 }
19817}
19818
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019819sub isCyclical($$)
19820{
19821 my ($Stack, $Value) = @_;
19822 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019823}
19824
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019825sub getGCC_Opts($)
19826{ # to use in module
19827 my $LibVersion = $_[0];
19828
19829 my @Opts = ();
19830
19831 if($CompilerOptions{$LibVersion})
19832 { # user-defined options
19833 push(@Opts, $CompilerOptions{$LibVersion});
19834 }
19835 if($GccOptions)
19836 { # additional
19837 push(@Opts, $GccOptions);
19838 }
19839
19840 if(@Opts) {
19841 return join(" ", @Opts);
19842 }
19843
19844 return undef;
19845}
19846
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019847sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019848{
19849 my $LibVersion = $_[0];
19850
19851 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19852 return $Cache{"getArch_GCC"}{$LibVersion};
19853 }
19854
19855 my $Arch = undef;
19856
19857 if($GCC_PATH)
19858 {
19859 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19860
19861 my $Cmd = $GCC_PATH." test.c -o test";
19862 if(my $Opts = getGCC_Opts($LibVersion))
19863 { # user-defined options
19864 $Cmd .= " ".$Opts;
19865 }
19866
19867 chdir($TMP_DIR);
19868 system($Cmd);
19869 chdir($ORIG_DIR);
19870
19871 $Arch = getArch_Object("$TMP_DIR/test");
19872
19873 unlink("$TMP_DIR/test.c");
19874 unlink("$TMP_DIR/test");
19875 }
19876
19877 if(not $Arch) {
19878 exitStatus("Error", "can't check ARCH type");
19879 }
19880
19881 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19882}
19883
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019884sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019885{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019886 my $LibVersion = $_[0];
19887
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019888 my $Size = undef;
19889
19890 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019891 if(my $Arch = getArch($LibVersion))
19892 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019893 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019894 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019895 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019896 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19897 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019898 }
19899 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019900
19901 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019902 {
19903 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019904
19905 my $Cmd = $GCC_PATH." -E -dD empty.h";
19906 if(my $Opts = getGCC_Opts($LibVersion))
19907 { # user-defined options
19908 $Cmd .= " ".$Opts;
19909 }
19910
19911 chdir($TMP_DIR);
19912 my $Defines = `$Cmd`;
19913 chdir($ORIG_DIR);
19914
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019915 unlink("$TMP_DIR/empty.h");
19916
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019917 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19918 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019919 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019920 }
19921 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19922 { # GCC 3
19923 my $PTRDIFF = $1;
19924 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019925 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019926 }
19927 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019928 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019929 }
19930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019931 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019932
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019933 if(not $Size) {
19934 exitStatus("Error", "can't check WORD size");
19935 }
19936
19937 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019938}
19939
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019940sub getWordSize($)
19941{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019942 return $WORD_SIZE{$_[0]};
19943}
19944
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019945sub majorVersion($)
19946{
19947 my $V = $_[0];
19948 return 0 if(not $V);
19949 my @VParts = split(/\./, $V);
19950 return $VParts[0];
19951}
19952
19953sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019954{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019955 my ($V1, $V2) = @_;
19956 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019957 my @V1Parts = split(/\./, $V1);
19958 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019959 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19960 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019961 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19962 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19963 }
19964 return -1 if($#V1Parts < $#V2Parts);
19965 return 1 if($#V1Parts > $#V2Parts);
19966 return 0;
19967}
19968
19969sub read_ABI_Dump($$)
19970{
19971 my ($LibVersion, $Path) = @_;
19972 return if(not $LibVersion or not -e $Path);
19973 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019974 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019975 { # input *.abi
19976 $FilePath = $Path;
19977 }
19978 else
19979 { # input *.abi.tar.gz
19980 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019981 if(not isDump_U($FilePath)) {
19982 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019984 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019985
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019986 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019987
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019988 my $Line = readLineNum($FilePath, 0);
19989 if($Line=~/xml/)
19990 { # XML format
19991 loadModule("XmlDump");
19992 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019993 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019994 else
19995 { # Perl Data::Dumper format (default)
19996 open(DUMP, $FilePath);
19997 local $/ = undef;
19998 my $Content = <DUMP>;
19999 close(DUMP);
20000
20001 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20002 { # remove temp file
20003 unlink($FilePath);
20004 }
20005 if($Content!~/};\s*\Z/) {
20006 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20007 }
20008 $ABI = eval($Content);
20009 if(not $ABI) {
20010 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020012 }
20013 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020014 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020015 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020016 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020017 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020018 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020020 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020021 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020022
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020023 if($ABI->{"PublicABI"}) {
20024 $UsedDump{$LibVersion}{"Public"} = 1;
20025 }
20026
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020027 if($ABI->{"ABI_DUMP_VERSION"})
20028 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020029 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020030 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020031 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020032 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020033 }
20034 else
20035 { # support for old ABI dumps
20036 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020037 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020038 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020039 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020040 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020041
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020042 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020043 {
20044 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 +040020045 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020046
20047 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20048 { # DWARF ABI Dump
20049 $UseConv_Real{$LibVersion}{"P"} = 1;
20050 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20051
20052 $UsedDump{$LibVersion}{"DWARF"} = 1;
20053
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020054 if(not $TargetComponent_Opt)
20055 {
20056 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20057 $TargetComponent = "module";
20058 }
20059 else {
20060 $TargetComponent = "object";
20061 }
20062 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020063 }
20064
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020065 if(not checkDump($LibVersion, "2.11"))
20066 { # old ABI dumps
20067 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020068 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020069 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020070 { # ABI dump created with --binary option
20071 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20072 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020073 else
20074 { # default
20075 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20076 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020077
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020078 if(defined $ABI->{"Mode"}
20079 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020080 { # --ext option
20081 $ExtendedCheck = 1;
20082 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020083 if($ABI->{"Extra"}) {
20084 $ExtraDump = 1;
20085 }
20086
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020087 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020088 {
20089 $UsedDump{$LibVersion}{"L"} = $Lang;
20090 setLanguage($LibVersion, $Lang);
20091 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020092 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020093 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020094 }
20095 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020096 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020097 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020098 if(not $TInfo)
20099 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020100 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020101 }
20102 my %Tid_TDid = ();
20103 foreach my $TDid (keys(%{$TInfo}))
20104 {
20105 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20106 {
20107 $MAX_ID = $Tid if($Tid>$MAX_ID);
20108 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020109 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020110 }
20111 }
20112 my %NewID = ();
20113 foreach my $Tid (keys(%Tid_TDid))
20114 {
20115 my @TDids = keys(%{$Tid_TDid{$Tid}});
20116 if($#TDids>=1)
20117 {
20118 foreach my $TDid (@TDids)
20119 {
20120 if($TDid) {
20121 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20122 }
20123 else
20124 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020125 my $ID = ++$MAX_ID;
20126
20127 $NewID{$TDid}{$Tid} = $ID;
20128 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20129 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020130 }
20131 }
20132 }
20133 else
20134 {
20135 my $TDid = $TDids[0];
20136 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20137 }
20138 }
20139 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20140 {
20141 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20142 if(defined $Info{"BaseType"})
20143 {
20144 my $Bid = $Info{"BaseType"}{"Tid"};
20145 my $BDid = $Info{"BaseType"}{"TDid"};
20146 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020147 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020148 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20149 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20150 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020151 }
20152 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020154 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020155 read_Machine_DumpInfo($ABI, $LibVersion);
20156 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020157 if(not $SymbolInfo{$LibVersion})
20158 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020159 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020160 }
20161 if(not keys(%{$SymbolInfo{$LibVersion}}))
20162 { # validation of old-version dumps
20163 if(not $ExtendedCheck) {
20164 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20165 }
20166 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020167 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020168 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020169 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020170 else
20171 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020172 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020173 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020174 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020175 }
20176 if(not $DepSymbols)
20177 { # Cannot reconstruct DepSymbols. This may result in false
20178 # positives if the old dump is for library 2. Not a problem if
20179 # old dumps are only from old libraries.
20180 $DepSymbols = {};
20181 }
20182 foreach my $Symbol (keys(%{$DepSymbols})) {
20183 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020185 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020186 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020187
20188 if(my $V = $TargetVersion{$LibVersion}) {
20189 $Descriptor{$LibVersion}{"Version"} = $V;
20190 }
20191 else {
20192 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20193 }
20194
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020195 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020196 { # if not defined by -skip-types option
20197 if(defined $ABI->{"SkipTypes"})
20198 {
20199 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20200 {
20201 $SkipTypes{$LibVersion}{$TName} = 1;
20202 }
20203 }
20204 if(defined $ABI->{"OpaqueTypes"})
20205 { # support for old dumps
20206 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20207 {
20208 $SkipTypes{$LibVersion}{$TName} = 1;
20209 }
20210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020211 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020212
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020213 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020214 { # if not defined by -skip-symbols option
20215 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20216 if(not $SkipSymbols{$LibVersion})
20217 { # support for old dumps
20218 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20219 }
20220 if(not $SkipSymbols{$LibVersion})
20221 { # support for old dumps
20222 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020224 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020225 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020226
20227 if(not $TargetHeaders{$LibVersion})
20228 { # if not defined by -headers-list option
20229 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20230 }
20231
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020232 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020233 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020234 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020235 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020236 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020237 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020238
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020239 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020240 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020241
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020242 if(not checkDump($LibVersion, "2.10.1")
20243 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020244 { # support for old ABI dumps: added target headers
20245 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020246 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020247 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020248
20249 if(not $ABI->{"PublicABI"})
20250 {
20251 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20252 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20253 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020255 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020256 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020257 if(defined $ABI->{"GccConstants"})
20258 { # 3.0
20259 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20260 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20261 }
20262 }
20263
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020264 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020265 if(not $NestedNameSpaces{$LibVersion})
20266 { # support for old dumps
20267 # Cannot reconstruct NameSpaces. This may affect design
20268 # of the compatibility report.
20269 $NestedNameSpaces{$LibVersion} = {};
20270 }
20271 # target system type
20272 # needed to adopt HTML report
20273 if(not $DumpSystem)
20274 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020275 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020276 }
20277 # recreate environment
20278 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20279 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020280 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020281 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020282 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20283 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020284 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020285 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020287 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20288 {
20289 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20290 setLanguage($LibVersion, "C++");
20291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020292 }
20293 }
20294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020295 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20296 {
20297 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20298 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20299 }
20300 }
20301
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020302 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020303 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020304 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020305 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020306 {
20307 if(not $Symbol_Library{$LibVersion}{$MnglName}
20308 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20309 push(@VFunc, $MnglName);
20310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020311 }
20312 }
20313 translateSymbols(@VFunc, $LibVersion);
20314 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020315 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20316
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020317 if(not checkDump($LibVersion, "3.0"))
20318 { # support for old ABI dumps
20319 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20320 {
20321 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20322 {
20323 if(ref($BaseType) eq "HASH") {
20324 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20325 }
20326 }
20327 }
20328 }
20329
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020330 if(not checkDump($LibVersion, "3.2"))
20331 { # support for old ABI dumps
20332 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20333 {
20334 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20335 {
20336 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20337 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20338 }
20339 }
20340 }
20341
20342 # repair target headers list
20343 delete($TargetHeaders{$LibVersion});
20344 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020345 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20346 }
20347 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20348 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020349 }
20350
20351 # non-target constants from anon enums
20352 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20353 {
20354 if(not $ExtraDump
20355 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20356 {
20357 delete($Constants{$LibVersion}{$Name});
20358 }
20359 }
20360 }
20361
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020362 if(not checkDump($LibVersion, "2.20"))
20363 { # support for old ABI dumps
20364 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20365 {
20366 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20367
20368 if($TType=~/Struct|Union|Enum|Typedef/)
20369 { # repair complex types first
20370 next;
20371 }
20372
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020373 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020374 {
20375 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20376 if($BType=~/Struct|Union|Enum/i)
20377 {
20378 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20379 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20380 }
20381 }
20382 }
20383 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20384 {
20385 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20386 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20387 if($TType=~/Struct|Union|Enum/) {
20388 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20389 }
20390 }
20391 }
20392
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020393 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020394 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020395 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20396 { # support for old ABI dumps < 2.0 (ACC 1.22)
20397 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20398 {
20399 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20400 {
20401 if($Access ne "public") {
20402 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20403 }
20404 }
20405 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20406 }
20407 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20408 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020409 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20410 { # support for old ABI dumps
20411 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20412 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020413 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20414 { # DWARF ABI Dumps
20415 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20416 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020417 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20418 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20419 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020420
20421 # support for old formatting of type names
20422 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20423
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020424 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20425 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020426 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020427 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20428 {
20429 if($SubId eq $TypeId)
20430 { # Fix erroneus ABI dump
20431 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20432 next;
20433 }
20434
20435 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020436 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020437 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020438 if($TInfo{"Type"} eq "MethodPtr")
20439 {
20440 if(defined $TInfo{"Param"})
20441 { # support for old ABI dumps <= 1.17
20442 if(not defined $TInfo{"Param"}{"0"})
20443 {
20444 my $Max = keys(%{$TInfo{"Param"}});
20445 foreach my $Pos (1 .. $Max) {
20446 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20447 }
20448 delete($TInfo{"Param"}{$Max});
20449 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20450 }
20451 }
20452 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020453 if($TInfo{"BaseType"} eq $TypeId)
20454 { # fix ABI dump
20455 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20456 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020457
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020458 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020459 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020460 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020462 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20463 if(not $BName)
20464 { # broken type
20465 next;
20466 }
20467 if($TInfo{"Name"} eq $BName)
20468 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020469 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020470 next;
20471 }
20472 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20473 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020474 }
20475 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020476 }
20477 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20478 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020479 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020480 }
20481 }
20482
20483 if(not checkDump($LibVersion, "2.15"))
20484 { # support for old ABI dumps
20485 my %Dups = ();
20486 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20487 {
20488 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020489 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020490 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20491 { # remove template decls
20492 delete($SymbolInfo{$LibVersion}{$InfoId});
20493 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020495 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020496 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20497 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020498 { # templates
20499 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020500 }
20501 }
20502 }
20503
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020504 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20505 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020506 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20507 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20508 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20509 { # support for old ABI dumps (< 3.1)
20510 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20511 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20512 { # add "this" first parameter
20513 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20514 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20515
20516 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20517 {
20518 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20519 foreach my $Pos (reverse(0 .. $#Pos)) {
20520 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20521 }
20522 }
20523 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20524 }
20525 }
20526
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020527 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20528 { # ABI dumps have no mangled names for C-functions
20529 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20530 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020531 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20532 { # support for old ABI dumps
20533 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20534 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020535 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20536 { # DWARF ABI Dumps
20537 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20538 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020539 }
20540
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020541 $Descriptor{$LibVersion}{"Dump"} = 1;
20542}
20543
20544sub read_Machine_DumpInfo($$)
20545{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020546 my ($ABI, $LibVersion) = @_;
20547 if($ABI->{"Arch"}) {
20548 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020550 if($ABI->{"WordSize"}) {
20551 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020552 }
20553 else
20554 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020555 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020556 }
20557 if(not $WORD_SIZE{$LibVersion})
20558 { # support for old dumps (<1.23)
20559 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20560 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020561 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020562 }
20563 else
20564 {
20565 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020566 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020567 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020568 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20569 { # any "pointer"-type
20570 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020571 last;
20572 }
20573 }
20574 if($PSize)
20575 { # a pointer type size
20576 $WORD_SIZE{$LibVersion} = $PSize;
20577 }
20578 else {
20579 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20580 }
20581 }
20582 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020583 if($ABI->{"GccVersion"}) {
20584 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020585 }
20586}
20587
20588sub read_Libs_DumpInfo($$)
20589{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020590 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020591 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20592 if(not $Library_Symbol{$LibVersion})
20593 { # support for old dumps
20594 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020596 if(keys(%{$Library_Symbol{$LibVersion}})
20597 and not $DumpAPI) {
20598 $Descriptor{$LibVersion}{"Libs"} = "OK";
20599 }
20600}
20601
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020602sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020603{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020604 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020605
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020606 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020607 and not $DumpAPI) {
20608 $Descriptor{$LibVersion}{"Headers"} = "OK";
20609 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020610 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020611 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020613 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020614 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020615
20616 if(keys(%{$ABI->{"Sources"}})
20617 and not $DumpAPI) {
20618 $Descriptor{$LibVersion}{"Sources"} = "OK";
20619 }
20620 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020621 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020622 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20623 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020625}
20626
20627sub find_libs($$$)
20628{
20629 my ($Path, $Type, $MaxDepth) = @_;
20630 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020631 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020632}
20633
20634sub createDescriptor($$)
20635{
20636 my ($LibVersion, $Path) = @_;
20637 if(not $LibVersion or not $Path
20638 or not -e $Path) {
20639 return "";
20640 }
20641 if(-d $Path)
20642 { # directory with headers files and shared objects
20643 return "
20644 <version>
20645 ".$TargetVersion{$LibVersion}."
20646 </version>
20647
20648 <headers>
20649 $Path
20650 </headers>
20651
20652 <libs>
20653 $Path
20654 </libs>";
20655 }
20656 else
20657 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020658 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020659 { # standard XML-descriptor
20660 return readFile($Path);
20661 }
20662 elsif(is_header($Path, 2, $LibVersion))
20663 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020664 $CheckHeadersOnly = 1;
20665
20666 if($LibVersion==1) {
20667 $TargetVersion{$LibVersion} = "X";
20668 }
20669
20670 if($LibVersion==2) {
20671 $TargetVersion{$LibVersion} = "Y";
20672 }
20673
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020674 return "
20675 <version>
20676 ".$TargetVersion{$LibVersion}."
20677 </version>
20678
20679 <headers>
20680 $Path
20681 </headers>
20682
20683 <libs>
20684 none
20685 </libs>";
20686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020687 else
20688 { # standard XML-descriptor
20689 return readFile($Path);
20690 }
20691 }
20692}
20693
20694sub detect_lib_default_paths()
20695{
20696 my %LPaths = ();
20697 if($OSgroup eq "bsd")
20698 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020699 if(my $LdConfig = get_CmdPath("ldconfig"))
20700 {
20701 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20702 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020703 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20704 {
20705 my $Name = "lib".$1;
20706 if(not defined $LPaths{$Name}) {
20707 $LPaths{$Name} = $2;
20708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020709 }
20710 }
20711 }
20712 else {
20713 printMsg("WARNING", "can't find ldconfig");
20714 }
20715 }
20716 else
20717 {
20718 if(my $LdConfig = get_CmdPath("ldconfig"))
20719 {
20720 if($SystemRoot and $OSgroup eq "linux")
20721 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20722 if(-e $SystemRoot."/etc/ld.so.conf") {
20723 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20724 }
20725 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020726 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20727 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020728 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20729 {
20730 my ($Name, $Path) = ($1, $2);
20731 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020732 if(not defined $LPaths{$Name})
20733 { # get first element from the list of available paths
20734
20735 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20736 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20737 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20738
20739 $LPaths{$Name} = $Path;
20740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020741 }
20742 }
20743 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020744 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020745 printMsg("WARNING", "can't find ldconfig");
20746 }
20747 }
20748 return \%LPaths;
20749}
20750
20751sub detect_bin_default_paths()
20752{
20753 my $EnvPaths = $ENV{"PATH"};
20754 if($OSgroup eq "beos") {
20755 $EnvPaths.=":".$ENV{"BETOOLS"};
20756 }
20757 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020758 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020759 {
20760 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020761 next if(not $Path);
20762 if($SystemRoot
20763 and $Path=~/\A\Q$SystemRoot\E\//)
20764 { # do NOT use binaries from target system
20765 next;
20766 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020767 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020768 }
20769}
20770
20771sub detect_inc_default_paths()
20772{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020773 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020774 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020775 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020776 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020777 next if(index($Line, "/cc1plus ")!=-1);
20778
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020779 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20780 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020781 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020782 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020783 if(index($Path, "c++")!=-1
20784 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020786 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787 if(not defined $MAIN_CPP_DIR
20788 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20789 $MAIN_CPP_DIR = $Path;
20790 }
20791 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020792 elsif(index($Path, "gcc")!=-1) {
20793 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020794 }
20795 else
20796 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020797 if($Path=~/local[\/\\]+include/)
20798 { # local paths
20799 next;
20800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020801 if($SystemRoot
20802 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20803 { # The GCC include path for user headers is not a part of the system root
20804 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20805 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20806 next;
20807 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020808 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020809 }
20810 }
20811 }
20812 unlink("$TMP_DIR/empty.h");
20813 return %DPaths;
20814}
20815
20816sub detect_default_paths($)
20817{
20818 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20819 my $Search = $_[0];
20820 if($Search!~/inc/) {
20821 $HSearch = 0;
20822 }
20823 if($Search!~/lib/) {
20824 $LSearch = 0;
20825 }
20826 if($Search!~/bin/) {
20827 $BSearch = 0;
20828 }
20829 if($Search!~/gcc/) {
20830 $GSearch = 0;
20831 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020832 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020833 { # <search_headers> section of the XML descriptor
20834 # do NOT search for systems headers
20835 $HSearch = 0;
20836 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020837 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020838 { # <search_libs> section of the XML descriptor
20839 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020840 $LSearch = 0;
20841 }
20842 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20843 { # additional search paths
20844 next if($Type eq "include" and not $HSearch);
20845 next if($Type eq "lib" and not $LSearch);
20846 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020847 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020848 }
20849 if($OSgroup ne "windows")
20850 { # unix-like
20851 foreach my $Type ("include", "lib", "bin")
20852 { # automatic detection of system "devel" directories
20853 next if($Type eq "include" and not $HSearch);
20854 next if($Type eq "lib" and not $LSearch);
20855 next if($Type eq "bin" and not $BSearch);
20856 my ($UsrDir, $RootDir) = ("/usr", "/");
20857 if($SystemRoot and $Type ne "bin")
20858 { # 1. search for target headers and libraries
20859 # 2. use host commands: ldconfig, readelf, etc.
20860 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20861 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020862 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020863 if(-d $RootDir."/".$Type)
20864 { # if "/lib" is symbolic link
20865 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020866 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020867 }
20868 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020869 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020870 }
20871 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020872 if(-d $UsrDir)
20873 {
20874 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020875 if(-d $UsrDir."/".$Type)
20876 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020877 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020878 }
20879 }
20880 }
20881 }
20882 if($BSearch)
20883 {
20884 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020885 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020886 }
20887 # check environment variables
20888 if($OSgroup eq "beos")
20889 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020890 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020891 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020892 if($_ eq ".") {
20893 next;
20894 }
20895 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20896 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20897 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020898 }
20899 }
20900 if($HSearch)
20901 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020902 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20903 split(/:|;/, $ENV{"BEINCLUDES"})
20904 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020905 }
20906 if($LSearch)
20907 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020908 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20909 split(/:|;/, $ENV{"BELIBRARIES"}),
20910 split(/:|;/, $ENV{"LIBRARY_PATH"})
20911 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020912 }
20913 }
20914 if($LSearch)
20915 { # using linker to get system paths
20916 if(my $LPaths = detect_lib_default_paths())
20917 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020918 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020919 foreach my $Name (keys(%{$LPaths}))
20920 {
20921 if($SystemRoot
20922 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20923 { # wrong ldconfig configuration
20924 # check your <sysroot>/etc/ld.so.conf
20925 next;
20926 }
20927 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020928 if(my $Dir = get_dirname($LPaths->{$Name})) {
20929 $Dirs{$Dir} = 1;
20930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020931 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020932 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020933 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020934 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020935 }
20936 if($BSearch)
20937 {
20938 if($CrossGcc)
20939 { # --cross-gcc=arm-linux-gcc
20940 if(-e $CrossGcc)
20941 { # absolute or relative path
20942 $GCC_PATH = get_abs_path($CrossGcc);
20943 }
20944 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20945 { # command name
20946 $GCC_PATH = $CrossGcc;
20947 }
20948 else {
20949 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20950 }
20951 if($GCC_PATH=~/\s/) {
20952 $GCC_PATH = "\"".$GCC_PATH."\"";
20953 }
20954 }
20955 }
20956 if($GSearch)
20957 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020958 if(not $CrossGcc)
20959 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020960 $GCC_PATH = get_CmdPath("gcc");
20961 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020962 if(not $GCC_PATH)
20963 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020964 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020965 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020966 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020967 { # select the latest version
20968 @GCCs = sort {$b cmp $a} @GCCs;
20969 if(check_gcc($GCCs[0], "3"))
20970 {
20971 $GCC_PATH = $GCCs[0];
20972 last;
20973 }
20974 }
20975 }
20976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020977 if(not $GCC_PATH) {
20978 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20979 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020980
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030020981 my $GCC_Ver = get_dumpversion($GCC_PATH);
20982 if($GCC_Ver eq "4.8")
20983 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
20984 my $Info = `$GCC_PATH --version`;
20985
20986 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
20987 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
20988 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
20989 $GCC_Ver = $2;
20990 }
20991 }
20992
20993 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020994 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020995 my $GccTarget = get_dumpmachine($GCC_PATH);
20996
20997 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020998 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020999 $OStarget = "linux";
21000 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021001 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021002 elsif($GccTarget=~/symbian/)
21003 {
21004 $OStarget = "symbian";
21005 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21006 }
21007
21008 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21009
21010 # check GCC version
21011 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21012 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021013 # introduced in 4.8 and fixed in 4.8.3
21014 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.");
21015
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021016 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021017 }
21018 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021019 else {
21020 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021021 }
21022 }
21023 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021024 {
21025 # GCC standard paths
21026 if($GCC_PATH and not $NoStdInc)
21027 {
21028 my %DPaths = detect_inc_default_paths();
21029 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21030 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21031 @DefaultIncPaths = @{$DPaths{"Inc"}};
21032 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21033 }
21034
21035 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021036 my $IncPath = "/usr/include";
21037 if($SystemRoot) {
21038 $IncPath = $SystemRoot.$IncPath;
21039 }
21040 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 }
21043 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021044
21045 if($ExtraInfo)
21046 {
21047 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21048 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021050}
21051
21052sub getLIB_EXT($)
21053{
21054 my $Target = $_[0];
21055 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21056 return $Ext;
21057 }
21058 return $OS_LibExt{$LIB_TYPE}{"default"};
21059}
21060
21061sub getAR_EXT($)
21062{
21063 my $Target = $_[0];
21064 if(my $Ext = $OS_Archive{$Target}) {
21065 return $Ext;
21066 }
21067 return $OS_Archive{"default"};
21068}
21069
21070sub get_dumpversion($)
21071{
21072 my $Cmd = $_[0];
21073 return "" if(not $Cmd);
21074 if($Cache{"get_dumpversion"}{$Cmd}) {
21075 return $Cache{"get_dumpversion"}{$Cmd};
21076 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021077 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021078 chomp($V);
21079 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21080}
21081
21082sub get_dumpmachine($)
21083{
21084 my $Cmd = $_[0];
21085 return "" if(not $Cmd);
21086 if($Cache{"get_dumpmachine"}{$Cmd}) {
21087 return $Cache{"get_dumpmachine"}{$Cmd};
21088 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021089 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021090 chomp($Machine);
21091 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21092}
21093
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021094sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021095{
21096 my $Cmd = $_[0];
21097 return "" if(not $Cmd);
21098 my @Options = (
21099 "--version",
21100 "-help"
21101 );
21102 foreach my $Opt (@Options)
21103 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021104 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021105 if($Info) {
21106 return 1;
21107 }
21108 }
21109 return 0;
21110}
21111
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021112sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021113{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021114 my ($Cmd, $ReqVer) = @_;
21115 return 0 if(not $Cmd or not $ReqVer);
21116 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21117 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021119 if(my $GccVer = get_dumpversion($Cmd))
21120 {
21121 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21122 if(cmpVersions($GccVer, $ReqVer)>=0) {
21123 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21124 }
21125 }
21126 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021127}
21128
21129sub get_depth($)
21130{
21131 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021132 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021133 }
21134 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21135}
21136
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021137sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021138{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021139 return if($Cache{"registerGccHeaders"}); # this function should be called once
21140
21141 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021142 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021143 my @Headers = cmd_find($Path,"f");
21144 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21145 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021146 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021147 my $FileName = get_filename($HPath);
21148 if(not defined $DefaultGccHeader{$FileName})
21149 { # skip duplicated
21150 $DefaultGccHeader{$FileName} = $HPath;
21151 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021152 }
21153 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021154 $Cache{"registerGccHeaders"} = 1;
21155}
21156
21157sub registerCppHeaders()
21158{
21159 return if($Cache{"registerCppHeaders"}); # this function should be called once
21160
21161 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021162 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021163 my @Headers = cmd_find($CppDir,"f");
21164 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21165 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021166 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021167 my $FileName = get_filename($Path);
21168 if(not defined $DefaultCppHeader{$FileName})
21169 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021170 $DefaultCppHeader{$FileName} = $Path;
21171 }
21172 }
21173 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021174 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021175}
21176
21177sub parse_libname($$$)
21178{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021179 return "" if(not $_[0]);
21180 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21181 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021182 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021183 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21184}
21185
21186sub parse_libname_I($$$)
21187{
21188 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021189
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021190 if($Target eq "symbian") {
21191 return parse_libname_symbian($Name, $Type);
21192 }
21193 elsif($Target eq "windows") {
21194 return parse_libname_windows($Name, $Type);
21195 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021196
21197 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021199 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021200 { # libSDL-1.2.so.0.7.1
21201 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021202 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021203 if($Type eq "name")
21204 { # libSDL-1.2
21205 # libwbxml2
21206 return $2;
21207 }
21208 elsif($Type eq "name+ext")
21209 { # libSDL-1.2.so
21210 # libwbxml2.so
21211 return $1;
21212 }
21213 elsif($Type eq "version")
21214 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021215 if(defined $7
21216 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217 { # 0.7.1
21218 return $7;
21219 }
21220 else
21221 { # libc-2.5.so (=>2.5 version)
21222 my $MV = $5;
21223 $MV=~s/\A[\-\_]+//g;
21224 return $MV;
21225 }
21226 }
21227 elsif($Type eq "short")
21228 { # libSDL
21229 # libwbxml2
21230 return $3;
21231 }
21232 elsif($Type eq "shortest")
21233 { # SDL
21234 # wbxml
21235 return shortest_name($3);
21236 }
21237 }
21238 return "";# error
21239}
21240
21241sub parse_libname_symbian($$)
21242{
21243 my ($Name, $Type) = @_;
21244 my $Ext = getLIB_EXT("symbian");
21245 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21246 { # libpthread{00010001}.dso
21247 if($Type eq "name")
21248 { # libpthread{00010001}
21249 return $2;
21250 }
21251 elsif($Type eq "name+ext")
21252 { # libpthread{00010001}.dso
21253 return $1;
21254 }
21255 elsif($Type eq "version")
21256 { # 00010001
21257 my $V = $4;
21258 $V=~s/\{(.+)\}/$1/;
21259 return $V;
21260 }
21261 elsif($Type eq "short")
21262 { # libpthread
21263 return $3;
21264 }
21265 elsif($Type eq "shortest")
21266 { # pthread
21267 return shortest_name($3);
21268 }
21269 }
21270 return "";# error
21271}
21272
21273sub parse_libname_windows($$)
21274{
21275 my ($Name, $Type) = @_;
21276 my $Ext = getLIB_EXT("windows");
21277 if($Name=~/((.+?)\.$Ext)\Z/)
21278 { # netapi32.dll
21279 if($Type eq "name")
21280 { # netapi32
21281 return $2;
21282 }
21283 elsif($Type eq "name+ext")
21284 { # netapi32.dll
21285 return $1;
21286 }
21287 elsif($Type eq "version")
21288 { # DLL version embedded
21289 # at binary-level
21290 return "";
21291 }
21292 elsif($Type eq "short")
21293 { # netapi32
21294 return $2;
21295 }
21296 elsif($Type eq "shortest")
21297 { # netapi
21298 return shortest_name($2);
21299 }
21300 }
21301 return "";# error
21302}
21303
21304sub shortest_name($)
21305{
21306 my $Name = $_[0];
21307 # remove prefix
21308 $Name=~s/\A(lib|open)//;
21309 # remove suffix
21310 $Name=~s/[\W\d_]+\Z//i;
21311 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21312 return $Name;
21313}
21314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021315sub createSymbolsList($$$$$)
21316{
21317 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021318
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021319 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021320 prepareSymbols(1);
21321
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021322 my %SymbolHeaderLib = ();
21323 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021324
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021325 # Get List
21326 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21327 {
21328 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021329 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021330 next;
21331 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021332 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021333 { # skip other symbols
21334 next;
21335 }
21336 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21337 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021338 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021339 next;
21340 }
21341 my $DyLib = $Symbol_Library{1}{$Symbol};
21342 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021343 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021344 next;
21345 }
21346 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21347 $Total+=1;
21348 }
21349 # Draw List
21350 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21351 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21352 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21353 {
21354 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21355 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021356 my %NS_Symbol = ();
21357 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021358 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021359 }
21360 foreach my $NameSpace (sort keys(%NS_Symbol))
21361 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021362 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021363 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21364 foreach my $Symbol (@SortedInterfaces)
21365 {
21366 my $SubReport = "";
21367 my $Signature = get_Signature($Symbol, 1);
21368 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021369 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021370 }
21371 if($Symbol=~/\A(_Z|\?)/)
21372 {
21373 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021374 $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 +040021375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021376 else {
21377 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21378 }
21379 }
21380 else
21381 {
21382 if($Signature) {
21383 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21384 }
21385 else {
21386 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21387 }
21388 }
21389 $SYMBOLS_LIST .= $SubReport;
21390 }
21391 }
21392 $SYMBOLS_LIST .= "<br/>\n";
21393 }
21394 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021395 # clear info
21396 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21397 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21398 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21399 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021400 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021401 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021402 my $CssStyles = readModule("Styles", "SymbolsList.css");
21403 my $JScripts = readModule("Scripts", "Sections.js");
21404 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021405 my $Title = "$LName: public symbols";
21406 my $Keywords = "$LName, API, symbols";
21407 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021408 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021410 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021411 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021412 writeFile($SaveTo, $SYMBOLS_LIST);
21413}
21414
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021415sub add_target_libs($)
21416{
21417 foreach (@{$_[0]}) {
21418 $TargetLibs{$_} = 1;
21419 }
21420}
21421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021422sub is_target_lib($)
21423{
21424 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021425 if(not $LName) {
21426 return 0;
21427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 if($TargetLibraryName
21429 and $LName!~/\Q$TargetLibraryName\E/) {
21430 return 0;
21431 }
21432 if(keys(%TargetLibs)
21433 and not $TargetLibs{$LName}
21434 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21435 return 0;
21436 }
21437 return 1;
21438}
21439
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021440sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021441{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021442 my ($H, $V) = @_;
21443 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021444 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021445 if($TargetHeaders{$V}{$H}) {
21446 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021447 }
21448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021449 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021450}
21451
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021452sub readLibs($)
21453{
21454 my $LibVersion = $_[0];
21455 if($OStarget eq "windows")
21456 { # dumpbin.exe will crash
21457 # without VS Environment
21458 check_win32_env();
21459 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021460 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021461 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021462 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021463}
21464
21465sub dump_sorting($)
21466{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021467 my $Hash = $_[0];
21468 return [] if(not $Hash);
21469 my @Keys = keys(%{$Hash});
21470 return [] if($#Keys<0);
21471 if($Keys[0]=~/\A\d+\Z/)
21472 { # numbers
21473 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021474 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021475 else
21476 { # strings
21477 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021478 }
21479}
21480
21481sub printMsg($$)
21482{
21483 my ($Type, $Msg) = @_;
21484 if($Type!~/\AINFO/) {
21485 $Msg = $Type.": ".$Msg;
21486 }
21487 if($Type!~/_C\Z/) {
21488 $Msg .= "\n";
21489 }
21490 if($Quiet)
21491 { # --quiet option
21492 appendFile($COMMON_LOG_PATH, $Msg);
21493 }
21494 else
21495 {
21496 if($Type eq "ERROR") {
21497 print STDERR $Msg;
21498 }
21499 else {
21500 print $Msg;
21501 }
21502 }
21503}
21504
21505sub exitStatus($$)
21506{
21507 my ($Code, $Msg) = @_;
21508 printMsg("ERROR", $Msg);
21509 exit($ERROR_CODE{$Code});
21510}
21511
21512sub exitReport()
21513{ # the tool has run without any errors
21514 printReport();
21515 if($COMPILE_ERRORS)
21516 { # errors in headers may add false positives/negatives
21517 exit($ERROR_CODE{"Compile_Error"});
21518 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021519 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21520 { # --binary
21521 exit($ERROR_CODE{"Incompatible"});
21522 }
21523 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21524 { # --source
21525 exit($ERROR_CODE{"Incompatible"});
21526 }
21527 elsif($RESULT{"Source"}{"Problems"}
21528 or $RESULT{"Binary"}{"Problems"})
21529 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021530 exit($ERROR_CODE{"Incompatible"});
21531 }
21532 else {
21533 exit($ERROR_CODE{"Compatible"});
21534 }
21535}
21536
21537sub readRules($)
21538{
21539 my $Kind = $_[0];
21540 if(not -f $RULES_PATH{$Kind}) {
21541 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21542 }
21543 my $Content = readFile($RULES_PATH{$Kind});
21544 while(my $Rule = parseTag(\$Content, "rule"))
21545 {
21546 my $RId = parseTag(\$Rule, "id");
21547 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21548 foreach my $Prop (@Properties) {
21549 if(my $Value = parseTag(\$Rule, lc($Prop)))
21550 {
21551 $Value=~s/\n[ ]*//;
21552 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21553 }
21554 }
21555 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21556 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21557 }
21558 else {
21559 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21560 }
21561 }
21562}
21563
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021564sub getReportPath($)
21565{
21566 my $Level = $_[0];
21567 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21568 if($Level eq "Binary")
21569 {
21570 if($BinaryReportPath)
21571 { # --bin-report-path
21572 return $BinaryReportPath;
21573 }
21574 elsif($OutputReportPath)
21575 { # --report-path
21576 return $OutputReportPath;
21577 }
21578 else
21579 { # default
21580 return $Dir."/abi_compat_report.$ReportFormat";
21581 }
21582 }
21583 elsif($Level eq "Source")
21584 {
21585 if($SourceReportPath)
21586 { # --src-report-path
21587 return $SourceReportPath;
21588 }
21589 elsif($OutputReportPath)
21590 { # --report-path
21591 return $OutputReportPath;
21592 }
21593 else
21594 { # default
21595 return $Dir."/src_compat_report.$ReportFormat";
21596 }
21597 }
21598 else
21599 {
21600 if($OutputReportPath)
21601 { # --report-path
21602 return $OutputReportPath;
21603 }
21604 else
21605 { # default
21606 return $Dir."/compat_report.$ReportFormat";
21607 }
21608 }
21609}
21610
21611sub printStatMsg($)
21612{
21613 my $Level = $_[0];
21614 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21615}
21616
21617sub listAffected($)
21618{
21619 my $Level = $_[0];
21620 my $List = "";
21621 foreach (keys(%{$TotalAffected{$Level}}))
21622 {
21623 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21624 { # skip "Low"-severity problems
21625 next;
21626 }
21627 $List .= "$_\n";
21628 }
21629 my $Dir = get_dirname(getReportPath($Level));
21630 if($Level eq "Binary") {
21631 writeFile($Dir."/abi_affected.txt", $List);
21632 }
21633 elsif($Level eq "Source") {
21634 writeFile($Dir."/src_affected.txt", $List);
21635 }
21636}
21637
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021638sub printReport()
21639{
21640 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021641 createReport();
21642 if($JoinReport or $DoubleReport)
21643 {
21644 if($RESULT{"Binary"}{"Problems"}
21645 or $RESULT{"Source"}{"Problems"}) {
21646 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021648 else {
21649 printMsg("INFO", "result: COMPATIBLE");
21650 }
21651 printStatMsg("Binary");
21652 printStatMsg("Source");
21653 if($ListAffected)
21654 { # --list-affected
21655 listAffected("Binary");
21656 listAffected("Source");
21657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021658 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021659 elsif($BinaryOnly)
21660 {
21661 if($RESULT{"Binary"}{"Problems"}) {
21662 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21663 }
21664 else {
21665 printMsg("INFO", "result: COMPATIBLE");
21666 }
21667 printStatMsg("Binary");
21668 if($ListAffected)
21669 { # --list-affected
21670 listAffected("Binary");
21671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021672 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021673 elsif($SourceOnly)
21674 {
21675 if($RESULT{"Source"}{"Problems"}) {
21676 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21677 }
21678 else {
21679 printMsg("INFO", "result: COMPATIBLE");
21680 }
21681 printStatMsg("Source");
21682 if($ListAffected)
21683 { # --list-affected
21684 listAffected("Source");
21685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021686 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021687 if($StdOut)
21688 {
21689 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021690 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021691 printMsg("INFO", "compatibility report has been generated to stdout");
21692 }
21693 else
21694 { # default
21695 printMsg("INFO", "compatibility reports have been generated to stdout");
21696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021698 else
21699 {
21700 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021701 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021702 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21703 }
21704 elsif($DoubleReport)
21705 { # default
21706 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21707 }
21708 elsif($BinaryOnly)
21709 { # --binary
21710 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21711 }
21712 elsif($SourceOnly)
21713 { # --source
21714 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021716 }
21717}
21718
21719sub check_win32_env()
21720{
21721 if(not $ENV{"DevEnvDir"}
21722 or not $ENV{"LIB"}) {
21723 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21724 }
21725}
21726
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021727sub diffSets($$)
21728{
21729 my ($S1, $S2) = @_;
21730 my @SK1 = keys(%{$S1});
21731 my @SK2 = keys(%{$S2});
21732 if($#SK1!=$#SK2) {
21733 return 1;
21734 }
21735 foreach my $K1 (@SK1)
21736 {
21737 if(not defined $S2->{$K1}) {
21738 return 1;
21739 }
21740 }
21741 return 0;
21742}
21743
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021744sub defaultDumpPath($$)
21745{
21746 my ($N, $V) = @_;
21747 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21748}
21749
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021750sub create_ABI_Dump()
21751{
21752 if(not -e $DumpAPI) {
21753 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21754 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021755
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021756 if(isDump($DumpAPI)) {
21757 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021758 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021759 else {
21760 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021761 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021762
21763 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021764 { # set to default: N
21765 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021766 }
21767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021768 initLogging(1);
21769 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021770
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021771 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021772 if($OutputDumpPath)
21773 { # user defined path
21774 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021775 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021776 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21777
21778 if(not $Archive and not $StdOut)
21779 { # check archive utilities
21780 if($OSgroup eq "windows")
21781 { # using zip
21782 my $ZipCmd = get_CmdPath("zip");
21783 if(not $ZipCmd) {
21784 exitStatus("Not_Found", "can't find \"zip\"");
21785 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021786 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021787 else
21788 { # using tar and gzip
21789 my $TarCmd = get_CmdPath("tar");
21790 if(not $TarCmd) {
21791 exitStatus("Not_Found", "can't find \"tar\"");
21792 }
21793 my $GzipCmd = get_CmdPath("gzip");
21794 if(not $GzipCmd) {
21795 exitStatus("Not_Found", "can't find \"gzip\"");
21796 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021797 }
21798 }
21799
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021800 if(not $Descriptor{1}{"Dump"})
21801 {
21802 if(not $CheckHeadersOnly) {
21803 readLibs(1);
21804 }
21805 if($CheckHeadersOnly) {
21806 setLanguage(1, "C++");
21807 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021808 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021809 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021810 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021811 if(not $Descriptor{1}{"Dump"})
21812 {
21813 if($Descriptor{1}{"Headers"}) {
21814 readHeaders(1);
21815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021816 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021817 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021818 if(not keys(%{$SymbolInfo{1}}))
21819 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021820 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021821 {
21822 if($CheckHeadersOnly) {
21823 exitStatus("Empty_Set", "the set of public symbols is empty");
21824 }
21825 else {
21826 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21827 }
21828 }
21829 }
21830 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021831 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021832 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21833 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021834 if($ExtraDump)
21835 { # add unmangled names to the ABI dump
21836 my @Names = ();
21837 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21838 {
21839 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21840 push(@Names, $MnglName);
21841 }
21842 }
21843 translateSymbols(@Names, 1);
21844 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21845 {
21846 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21847 {
21848 if(my $Unmangled = $tr_name{$MnglName})
21849 {
21850 if($MnglName ne $Unmangled) {
21851 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21852 }
21853 }
21854 }
21855 }
21856 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021857
21858 my %GccConstants = (); # built-in GCC constants
21859 foreach my $Name (keys(%{$Constants{1}}))
21860 {
21861 if(not defined $Constants{1}{$Name}{"Header"})
21862 {
21863 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21864 delete($Constants{1}{$Name});
21865 }
21866 }
21867
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021868 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021869 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021870 "TypeInfo" => $TypeInfo{1},
21871 "SymbolInfo" => $SymbolInfo{1},
21872 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021873 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021874 "SymbolVersion" => $SymVer{1},
21875 "LibraryVersion" => $Descriptor{1}{"Version"},
21876 "LibraryName" => $TargetLibraryName,
21877 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021878 "SkipTypes" => $SkipTypes{1},
21879 "SkipSymbols" => $SkipSymbols{1},
21880 "SkipNameSpaces" => $SkipNameSpaces{1},
21881 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021882 "Headers" => \%HeadersInfo,
21883 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021884 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021885 "NameSpaces" => $NestedNameSpaces{1},
21886 "Target" => $OStarget,
21887 "Arch" => getArch(1),
21888 "WordSize" => $WORD_SIZE{1},
21889 "GccVersion" => get_dumpversion($GCC_PATH),
21890 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21891 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21892 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021893 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021894 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021895 }
21896 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021897 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021899 if($ExtendedCheck)
21900 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021901 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021902 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021903 if($BinaryOnly)
21904 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021905 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021906 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021907 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021908 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021909 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021910 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21911 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021912 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021913
21914 my $ABI_DUMP = "";
21915 if($UseXML)
21916 {
21917 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021918 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021920 else
21921 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021922 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021924 if($StdOut)
21925 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021926 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021927 printMsg("INFO", "ABI dump has been generated to stdout");
21928 return;
21929 }
21930 else
21931 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021932 my ($DDir, $DName) = separate_path($DumpPath);
21933 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021934 if(not $Archive) {
21935 $DPath = $DumpPath;
21936 }
21937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021938 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021939
21940 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021941 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021942 close(DUMP);
21943
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021944 if(not -s $DPath) {
21945 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21946 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021947 if($Archive) {
21948 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021949 }
21950
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021951 if($OutputDumpPath) {
21952 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021953 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021954 else {
21955 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21956 }
21957 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 +040021958 }
21959}
21960
21961sub quickEmptyReports()
21962{ # Quick "empty" reports
21963 # 4 times faster than merging equal dumps
21964 # NOTE: the dump contains the "LibraryVersion" attribute
21965 # if you change the version, then your dump will be different
21966 # OVERCOME: use -v1 and v2 options for comparing dumps
21967 # and don't change version in the XML descriptor (and dumps)
21968 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21969 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21970 {
21971 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21972 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21973 if($FilePath1 and $FilePath2)
21974 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021975 my $Line = readLineNum($FilePath1, 0);
21976 if($Line=~/xml/)
21977 { # XML format
21978 # is not supported yet
21979 return;
21980 }
21981
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021982 local $/ = undef;
21983
21984 open(DUMP1, $FilePath1);
21985 my $Content1 = <DUMP1>;
21986 close(DUMP1);
21987
21988 open(DUMP2, $FilePath2);
21989 my $Content2 = <DUMP2>;
21990 close(DUMP2);
21991
21992 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021993 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021994 # clean memory
21995 undef $Content2;
21996
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021997 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021998 my $ABIdump = eval($Content1);
21999
22000 # clean memory
22001 undef $Content1;
22002
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022003 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022004 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 +040022005 }
22006 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022007 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022008 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22009 }
22010 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022011 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022012 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22013 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022014 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022015 read_Libs_DumpInfo($ABIdump, 1);
22016 read_Machine_DumpInfo($ABIdump, 1);
22017 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022018
22019 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22020 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22021
22022 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
22023 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
22024
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022025 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22026 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22027 exitReport();
22028 }
22029 }
22030 }
22031}
22032
22033sub initLogging($)
22034{
22035 my $LibVersion = $_[0];
22036 # create log directory
22037 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22038 if($OutputLogPath{$LibVersion})
22039 { # user-defined by -log-path option
22040 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22041 }
22042 if($LogMode ne "n") {
22043 mkpath($LOG_DIR);
22044 }
22045 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022046 if($Debug)
22047 { # debug directory
22048 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022049
22050 if(not $ExtraInfo)
22051 { # enable --extra-info
22052 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022054 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022055 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022056}
22057
22058sub writeLog($$)
22059{
22060 my ($LibVersion, $Msg) = @_;
22061 if($LogMode ne "n") {
22062 appendFile($LOG_PATH{$LibVersion}, $Msg);
22063 }
22064}
22065
22066sub resetLogging($)
22067{
22068 my $LibVersion = $_[0];
22069 if($LogMode!~/a|n/)
22070 { # remove old log
22071 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022072 if($Debug) {
22073 rmtree($DEBUG_PATH{$LibVersion});
22074 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022075 }
22076}
22077
22078sub printErrorLog($)
22079{
22080 my $LibVersion = $_[0];
22081 if($LogMode ne "n") {
22082 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22083 }
22084}
22085
22086sub isDump($)
22087{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022088 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22089 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022090 return $1;
22091 }
22092 return 0;
22093}
22094
22095sub isDump_U($)
22096{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022097 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022098 return $1;
22099 }
22100 return 0;
22101}
22102
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022103sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022104{
22105 # read input XML descriptors or ABI dumps
22106 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022107 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022108 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022109 if(not -e $Descriptor{1}{"Path"}) {
22110 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022111 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022112
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022113 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022114 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022115 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022116 if(not -e $Descriptor{2}{"Path"}) {
22117 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022118 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022119
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022120 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022121 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022122 and isDump($Descriptor{2}{"Path"}))
22123 { # optimization: equal ABI dumps
22124 quickEmptyReports();
22125 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022127 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022128
22129 if(isDump($Descriptor{1}{"Path"})) {
22130 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022131 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022132 else {
22133 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22134 }
22135
22136 if(isDump($Descriptor{2}{"Path"})) {
22137 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22138 }
22139 else {
22140 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022141 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022142
22143 if(not $Descriptor{1}{"Version"})
22144 { # set to default: X
22145 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022146 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022147 }
22148
22149 if(not $Descriptor{2}{"Version"})
22150 { # set to default: Y
22151 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022152 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022153 }
22154
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022155 if(not $UsedDump{1}{"V"}) {
22156 initLogging(1);
22157 }
22158
22159 if(not $UsedDump{2}{"V"}) {
22160 initLogging(2);
22161 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022162
22163 # check input data
22164 if(not $Descriptor{1}{"Headers"}) {
22165 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022166 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022167 if(not $Descriptor{2}{"Headers"}) {
22168 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022169 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022170
22171 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022172 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022173 if(not $Descriptor{1}{"Libs"}) {
22174 exitStatus("Error", "can't find libraries info in descriptor d1");
22175 }
22176 if(not $Descriptor{2}{"Libs"}) {
22177 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022178 }
22179 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022180
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022181 if($UseDumps)
22182 { # --use-dumps
22183 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022184 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22185 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022186
22187 unlink($DumpPath1);
22188 unlink($DumpPath2);
22189
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022190 my $pid = fork();
22191 if($pid)
22192 { # dump on two CPU cores
22193 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22194 if($RelativeDirectory{1}) {
22195 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22196 }
22197 if($OutputLogPath{1}) {
22198 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22199 }
22200 if($CrossGcc) {
22201 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22202 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022203 if($Quiet)
22204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022205 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022206 @PARAMS = (@PARAMS, "-logging-mode", "a");
22207 }
22208 elsif($LogMode and $LogMode ne "w")
22209 { # "w" is default
22210 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022211 }
22212 if($ExtendedCheck) {
22213 @PARAMS = (@PARAMS, "-extended");
22214 }
22215 if($UserLang) {
22216 @PARAMS = (@PARAMS, "-lang", $UserLang);
22217 }
22218 if($TargetVersion{1}) {
22219 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22220 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022221 if($BinaryOnly) {
22222 @PARAMS = (@PARAMS, "-binary");
22223 }
22224 if($SourceOnly) {
22225 @PARAMS = (@PARAMS, "-source");
22226 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022227 if($SortDump) {
22228 @PARAMS = (@PARAMS, "-sort");
22229 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022230 if($DumpFormat and $DumpFormat ne "perl") {
22231 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22232 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022233 if($CheckHeadersOnly) {
22234 @PARAMS = (@PARAMS, "-headers-only");
22235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022236 if($Debug)
22237 {
22238 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022239 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022241 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022242 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022243 exit(1);
22244 }
22245 }
22246 else
22247 { # child
22248 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22249 if($RelativeDirectory{2}) {
22250 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22251 }
22252 if($OutputLogPath{2}) {
22253 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22254 }
22255 if($CrossGcc) {
22256 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22257 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022258 if($Quiet)
22259 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022260 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022261 @PARAMS = (@PARAMS, "-logging-mode", "a");
22262 }
22263 elsif($LogMode and $LogMode ne "w")
22264 { # "w" is default
22265 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022266 }
22267 if($ExtendedCheck) {
22268 @PARAMS = (@PARAMS, "-extended");
22269 }
22270 if($UserLang) {
22271 @PARAMS = (@PARAMS, "-lang", $UserLang);
22272 }
22273 if($TargetVersion{2}) {
22274 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22275 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022276 if($BinaryOnly) {
22277 @PARAMS = (@PARAMS, "-binary");
22278 }
22279 if($SourceOnly) {
22280 @PARAMS = (@PARAMS, "-source");
22281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022282 if($SortDump) {
22283 @PARAMS = (@PARAMS, "-sort");
22284 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022285 if($DumpFormat and $DumpFormat ne "perl") {
22286 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22287 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022288 if($CheckHeadersOnly) {
22289 @PARAMS = (@PARAMS, "-headers-only");
22290 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022291 if($Debug)
22292 {
22293 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022294 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022296 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022297 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022298 exit(1);
22299 }
22300 else {
22301 exit(0);
22302 }
22303 }
22304 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022306 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022307 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22308 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022309 if($TargetTitle ne $TargetLibraryName) {
22310 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022311 }
22312 if($ShowRetVal) {
22313 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22314 }
22315 if($CrossGcc) {
22316 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22317 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022318 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22319 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022320 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022321 }
22322 if($ReportFormat and $ReportFormat ne "html")
22323 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022324 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22325 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022326 if($OutputReportPath) {
22327 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22328 }
22329 if($BinaryReportPath) {
22330 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22331 }
22332 if($SourceReportPath) {
22333 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22334 }
22335 if($LoggingPath) {
22336 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22337 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022338 if($CheckHeadersOnly) {
22339 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22340 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022341 if($BinaryOnly) {
22342 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22343 }
22344 if($SourceOnly) {
22345 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22346 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022347 if($Debug)
22348 {
22349 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22350 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022352 system("perl", $0, @CMP_PARAMS);
22353 exit($?>>8);
22354 }
22355 if(not $Descriptor{1}{"Dump"}
22356 or not $Descriptor{2}{"Dump"})
22357 { # need GCC toolchain to analyze
22358 # header files and libraries
22359 detect_default_paths("inc|lib|gcc");
22360 }
22361 if(not $Descriptor{1}{"Dump"})
22362 {
22363 if(not $CheckHeadersOnly) {
22364 readLibs(1);
22365 }
22366 if($CheckHeadersOnly) {
22367 setLanguage(1, "C++");
22368 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022369 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022370 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022371 }
22372 if(not $Descriptor{2}{"Dump"})
22373 {
22374 if(not $CheckHeadersOnly) {
22375 readLibs(2);
22376 }
22377 if($CheckHeadersOnly) {
22378 setLanguage(2, "C++");
22379 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022380 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022381 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022382 }
22383 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22384 { # support for old ABI dumps
22385 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022386 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022387 {
22388 $WORD_SIZE{1} = $WORD_SIZE{2};
22389 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22390 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022391 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022392 {
22393 $WORD_SIZE{2} = $WORD_SIZE{1};
22394 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22395 }
22396 }
22397 elsif(not $WORD_SIZE{1}
22398 and not $WORD_SIZE{2})
22399 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022400 $WORD_SIZE{1} = "4";
22401 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022402 }
22403 if($Descriptor{1}{"Dump"})
22404 { # support for old ABI dumps
22405 prepareTypes(1);
22406 }
22407 if($Descriptor{2}{"Dump"})
22408 { # support for old ABI dumps
22409 prepareTypes(2);
22410 }
22411 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22412 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22413 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022414 # process input data
22415 if($Descriptor{1}{"Headers"}
22416 and not $Descriptor{1}{"Dump"}) {
22417 readHeaders(1);
22418 }
22419 if($Descriptor{2}{"Headers"}
22420 and not $Descriptor{2}{"Dump"}) {
22421 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022422 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022423
22424 # clean memory
22425 %SystemHeaders = ();
22426 %mangled_name_gcc = ();
22427
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022428 prepareSymbols(1);
22429 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022430
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022431 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022432 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022433
22434 # Virtual Tables
22435 registerVTable(1);
22436 registerVTable(2);
22437
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022438 if(not checkDump(1, "1.22")
22439 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022440 { # support for old ABI dumps
22441 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22442 {
22443 if($ClassName=~/</)
22444 { # templates
22445 if(not defined $VirtualTable{1}{$ClassName})
22446 { # synchronize
22447 delete($VirtualTable{2}{$ClassName});
22448 }
22449 }
22450 }
22451 }
22452
22453 registerOverriding(1);
22454 registerOverriding(2);
22455
22456 setVirtFuncPositions(1);
22457 setVirtFuncPositions(2);
22458
22459 # Other
22460 addParamNames(1);
22461 addParamNames(2);
22462
22463 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022464}
22465
22466sub compareAPIs($)
22467{
22468 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022469
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022470 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022471 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022472
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022473 if($Level eq "Binary") {
22474 printMsg("INFO", "comparing ABIs ...");
22475 }
22476 else {
22477 printMsg("INFO", "comparing APIs ...");
22478 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022479
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022480 if($CheckHeadersOnly
22481 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022482 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022483 detectAdded_H($Level);
22484 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022485 }
22486 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022487 { # added/removed in libs
22488 detectAdded($Level);
22489 detectRemoved($Level);
22490 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022491
22492 mergeSymbols($Level);
22493 if(keys(%{$CheckedSymbols{$Level}})) {
22494 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022495 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022496
22497 $Cache{"mergeTypes"} = (); # free memory
22498
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022499 if($CheckHeadersOnly
22500 or $Level eq "Source")
22501 { # added/removed in headers
22502 mergeHeaders($Level);
22503 }
22504 else
22505 { # added/removed in libs
22506 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022507 }
22508}
22509
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022510sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022511{
22512 my %Opts = (
22513 "OStarget"=>$OStarget,
22514 "Debug"=>$Debug,
22515 "Quiet"=>$Quiet,
22516 "LogMode"=>$LogMode,
22517 "CheckHeadersOnly"=>$CheckHeadersOnly,
22518
22519 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022520 "GCC_PATH"=>$GCC_PATH,
22521 "TargetSysInfo"=>$TargetSysInfo,
22522 "CrossPrefix"=>$CrossPrefix,
22523 "TargetLibraryName"=>$TargetLibraryName,
22524 "CrossGcc"=>$CrossGcc,
22525 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022526 "NoStdInc"=>$NoStdInc,
22527
22528 "BinaryOnly" => $BinaryOnly,
22529 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022530 );
22531 return \%Opts;
22532}
22533
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022534sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022535{
22536 my %CODE_ERROR = reverse(%ERROR_CODE);
22537 return $CODE_ERROR{$_[0]};
22538}
22539
22540sub scenario()
22541{
22542 if($StdOut)
22543 { # enable quiet mode
22544 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022545 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022546 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022547 if(not $LogMode)
22548 { # default
22549 $LogMode = "w";
22550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022551 if($UserLang)
22552 { # --lang=C++
22553 $UserLang = uc($UserLang);
22554 $COMMON_LANGUAGE{1}=$UserLang;
22555 $COMMON_LANGUAGE{2}=$UserLang;
22556 }
22557 if($LoggingPath)
22558 {
22559 $OutputLogPath{1} = $LoggingPath;
22560 $OutputLogPath{2} = $LoggingPath;
22561 if($Quiet) {
22562 $COMMON_LOG_PATH = $LoggingPath;
22563 }
22564 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022565
22566 if($SkipInternalSymbols) {
22567 $SkipInternalSymbols=~s/\*/.*/g;
22568 }
22569
22570 if($SkipInternalTypes) {
22571 $SkipInternalTypes=~s/\*/.*/g;
22572 }
22573
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022574 if($Quick) {
22575 $ADD_TMPL_INSTANCES = 0;
22576 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022577 if($OutputDumpPath)
22578 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022579 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022580 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22581 }
22582 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022583 if($BinaryOnly and $SourceOnly)
22584 { # both --binary and --source
22585 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022586 if(not $CmpSystems)
22587 {
22588 $BinaryOnly = 0;
22589 $SourceOnly = 0;
22590 }
22591
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022592 $DoubleReport = 1;
22593 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022594
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022595 if($OutputReportPath)
22596 { # --report-path
22597 $DoubleReport = 0;
22598 $JoinReport = 1;
22599 }
22600 }
22601 elsif($BinaryOnly or $SourceOnly)
22602 { # --binary or --source
22603 $DoubleReport = 0;
22604 $JoinReport = 0;
22605 }
22606 if($UseXML)
22607 { # --xml option
22608 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022609 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022611 if($ReportFormat)
22612 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022613 $ReportFormat = lc($ReportFormat);
22614 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022615 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022616 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022617 if($ReportFormat eq "htm")
22618 { # HTM == HTML
22619 $ReportFormat = "html";
22620 }
22621 elsif($ReportFormat eq "xml")
22622 { # --report-format=XML equal to --xml
22623 $UseXML = 1;
22624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022625 }
22626 else
22627 { # default: HTML
22628 $ReportFormat = "html";
22629 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022630 if($DumpFormat)
22631 { # validate
22632 $DumpFormat = lc($DumpFormat);
22633 if($DumpFormat!~/\A(xml|perl)\Z/) {
22634 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22635 }
22636 if($DumpFormat eq "xml")
22637 { # --dump-format=XML equal to --xml
22638 $UseXML = 1;
22639 }
22640 }
22641 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022642 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022643 $DumpFormat = "perl";
22644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022645 if($Quiet and $LogMode!~/a|n/)
22646 { # --quiet log
22647 if(-f $COMMON_LOG_PATH) {
22648 unlink($COMMON_LOG_PATH);
22649 }
22650 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022651 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022652 $CheckUndefined = 1;
22653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022654 if($TestTool and $UseDumps)
22655 { # --test && --use-dumps == --test-dump
22656 $TestDump = 1;
22657 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022658 if($Tolerant)
22659 { # enable all
22660 $Tolerance = 1234;
22661 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022662 if($Help)
22663 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022664 HELP_MESSAGE();
22665 exit(0);
22666 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022667 if($InfoMsg)
22668 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022669 INFO_MESSAGE();
22670 exit(0);
22671 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022672 if($ShowVersion)
22673 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022674 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 +040022675 exit(0);
22676 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022677 if($DumpVersion)
22678 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022679 printMsg("INFO", $TOOL_VERSION);
22680 exit(0);
22681 }
22682 if($ExtendedCheck) {
22683 $CheckHeadersOnly = 1;
22684 }
22685 if($SystemRoot_Opt)
22686 { # user defined root
22687 if(not -e $SystemRoot_Opt) {
22688 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22689 }
22690 $SystemRoot = $SystemRoot_Opt;
22691 $SystemRoot=~s/[\/]+\Z//g;
22692 if($SystemRoot) {
22693 $SystemRoot = get_abs_path($SystemRoot);
22694 }
22695 }
22696 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022697
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022698 if($SortDump)
22699 {
22700 $Data::Dumper::Useperl = 1;
22701 $Data::Dumper::Sortkeys = \&dump_sorting;
22702 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022703
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022704 if($TargetLibsPath)
22705 {
22706 if(not -f $TargetLibsPath) {
22707 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22708 }
22709 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22710 $TargetLibs{$Lib} = 1;
22711 }
22712 }
22713 if($TargetHeadersPath)
22714 { # --headers-list
22715 if(not -f $TargetHeadersPath) {
22716 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22717 }
22718 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22719 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022720 $TargetHeaders{1}{get_filename($Header)} = 1;
22721 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022722 }
22723 }
22724 if($TargetHeader)
22725 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022726 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22727 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022728 }
22729 if($TestTool
22730 or $TestDump)
22731 { # --test, --test-dump
22732 detect_default_paths("bin|gcc"); # to compile libs
22733 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022734 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022735 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022736 exit(0);
22737 }
22738 if($DumpSystem)
22739 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022740
22741 if(not $TargetSysInfo) {
22742 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22743 }
22744
22745 if(not -d $TargetSysInfo) {
22746 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22747 }
22748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022749 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022750 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022751 { # system XML descriptor
22752 if(not -f $DumpSystem) {
22753 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22754 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022755
22756 my $SDesc = readFile($DumpSystem);
22757 if(my $RelDir = $RelativeDirectory{1}) {
22758 $SDesc =~ s/{RELPATH}/$RelDir/g;
22759 }
22760
22761 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022762 foreach (@{$Ret->{"Tools"}})
22763 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022764 push_U($SystemPaths{"bin"}, $_);
22765 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022766 }
22767 if($Ret->{"CrossPrefix"}) {
22768 $CrossPrefix = $Ret->{"CrossPrefix"};
22769 }
22770 }
22771 elsif($SystemRoot_Opt)
22772 { # -sysroot "/" option
22773 # default target: /usr/lib, /usr/include
22774 # search libs: /usr/lib and /lib
22775 if(not -e $SystemRoot."/usr/lib") {
22776 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22777 }
22778 if(not -e $SystemRoot."/lib") {
22779 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22780 }
22781 if(not -e $SystemRoot."/usr/include") {
22782 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22783 }
22784 readSystemDescriptor("
22785 <name>
22786 $DumpSystem
22787 </name>
22788 <headers>
22789 $SystemRoot/usr/include
22790 </headers>
22791 <libs>
22792 $SystemRoot/usr/lib
22793 </libs>
22794 <search_libs>
22795 $SystemRoot/lib
22796 </search_libs>");
22797 }
22798 else {
22799 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22800 }
22801 detect_default_paths("bin|gcc"); # to check symbols
22802 if($OStarget eq "windows")
22803 { # to run dumpbin.exe
22804 # and undname.exe
22805 check_win32_env();
22806 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022807 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022808 exit(0);
22809 }
22810 if($CmpSystems)
22811 { # --cmp-systems
22812 detect_default_paths("bin"); # to extract dumps
22813 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022814 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022815 exit(0);
22816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022817 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022818 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022819 }
22820 else
22821 { # validate library name
22822 if($TargetLibraryName=~/[\*\/\\]/) {
22823 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22824 }
22825 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022826 if(not $TargetTitle) {
22827 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022828 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022829
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022830 if($SymbolsListPath)
22831 {
22832 if(not -f $SymbolsListPath) {
22833 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22834 }
22835 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22836 $SymbolsList{$Interface} = 1;
22837 }
22838 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022839 if($TypesListPath)
22840 {
22841 if(not -f $TypesListPath) {
22842 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22843 }
22844 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22845 $TypesList{$Type} = 1;
22846 }
22847 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022848 if($SkipSymbolsListPath)
22849 {
22850 if(not -f $SkipSymbolsListPath) {
22851 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22852 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022853 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22854 {
22855 $SkipSymbols{1}{$Interface} = 1;
22856 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022857 }
22858 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030022859 if($SkipTypesListPath)
22860 {
22861 if(not -f $SkipTypesListPath) {
22862 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
22863 }
22864 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
22865 {
22866 $SkipTypes{1}{$Type} = 1;
22867 $SkipTypes{2}{$Type} = 1;
22868 }
22869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022870 if($SkipHeadersPath)
22871 {
22872 if(not -f $SkipHeadersPath) {
22873 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22874 }
22875 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022876 { # register for both versions
22877 $SkipHeadersList{1}{$Path} = 1;
22878 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022879 my ($CPath, $Type) = classifyPath($Path);
22880 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022881 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022882 }
22883 }
22884 if($ParamNamesPath)
22885 {
22886 if(not -f $ParamNamesPath) {
22887 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22888 }
22889 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22890 {
22891 if($Line=~s/\A(\w+)\;//)
22892 {
22893 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022894 if($Line=~/;(\d+);/)
22895 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022896 while($Line=~s/(\d+);(\w+)//) {
22897 $AddIntParams{$Interface}{$1}=$2;
22898 }
22899 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022900 else
22901 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022902 my $Num = 0;
22903 foreach my $Name (split(/;/, $Line)) {
22904 $AddIntParams{$Interface}{$Num++}=$Name;
22905 }
22906 }
22907 }
22908 }
22909 }
22910 if($AppPath)
22911 {
22912 if(not -f $AppPath) {
22913 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22914 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022915
22916 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022917 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022918 $SymbolsList_App{$Interface} = 1;
22919 }
22920 }
22921 if($DumpAPI)
22922 { # --dump-abi
22923 # make an API dump
22924 create_ABI_Dump();
22925 exit($COMPILE_ERRORS);
22926 }
22927 # default: compare APIs
22928 # -d1 <path>
22929 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022930 compareInit();
22931 if($JoinReport or $DoubleReport)
22932 {
22933 compareAPIs("Binary");
22934 compareAPIs("Source");
22935 }
22936 elsif($BinaryOnly) {
22937 compareAPIs("Binary");
22938 }
22939 elsif($SourceOnly) {
22940 compareAPIs("Source");
22941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022942 exitReport();
22943}
22944
22945scenario();