blob: 6f77622ddd2f212cc5134994cd4825c5f39d4d6b [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03003# ABI Compliance Checker (ABICC) 1.99.10
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 Ponomarenko52b2e352015-08-11 22:45:36 +03008# Copyright (C) 2012-2013 ROSA Laboratory
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +03009# Copyright (C) 2013-2015 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 Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040030# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040039# COMPATIBILITY
40# =============
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030041# ABI Dumper >= 0.99.9
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040042#
43#
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040044# This program is free software: you can redistribute it and/or modify
45# it under the terms of the GNU General Public License or the GNU Lesser
46# General Public License as published by the Free Software Foundation.
47#
48# This program is distributed in the hope that it will be useful,
49# but WITHOUT ANY WARRANTY; without even the implied warranty of
50# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51# GNU General Public License for more details.
52#
53# You should have received a copy of the GNU General Public License
54# and the GNU Lesser General Public License along with this program.
55# If not, see <http://www.gnu.org/licenses/>.
56###########################################################################
57use Getopt::Long;
58Getopt::Long::Configure ("posix_default", "no_ignore_case");
59use File::Path qw(mkpath rmtree);
60use File::Temp qw(tempdir);
61use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040062use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040063use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040064use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040065use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040066
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030067my $TOOL_VERSION = "1.99.10";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040068my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040069my $OLDEST_SUPPORTED_VERSION = "1.18";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040070my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040071my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040072my $OSgroup = get_OSgroup();
73my $ORIG_DIR = cwd();
74my $TMP_DIR = tempdir(CLEANUP=>1);
75
76# Internal modules
77my $MODULES_DIR = get_Modules();
78push(@INC, get_dirname($MODULES_DIR));
79# Rules DB
80my %RULES_PATH = (
81 "Binary" => $MODULES_DIR."/RulesBin.xml",
82 "Source" => $MODULES_DIR."/RulesSrc.xml");
83
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030084my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
86$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030087%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040088%TargetVersion, $InfoMsg, $UseOldDumps, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040089$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
90$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
91$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040092$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040093$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030094$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040095$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat, $SkipInternal,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030097$TargetArch, $GccOptions, $TypesListPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040098
99my $CmdName = get_filename($0);
100my %OS_LibExt = (
101 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400103 "macos"=>"dylib",
104 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400105 "symbian"=>"dso",
106 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400107 },
108 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400109 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400110 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400111 "symbian"=>"lib",
112 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400113 }
114);
115
116my %OS_Archive = (
117 "windows"=>"zip",
118 "default"=>"tar.gz"
119);
120
121my %ERROR_CODE = (
122 # Compatible verdict
123 "Compatible"=>0,
124 "Success"=>0,
125 # Incompatible verdict
126 "Incompatible"=>1,
127 # Undifferentiated error code
128 "Error"=>2,
129 # System command is not found
130 "Not_Found"=>3,
131 # Cannot access input files
132 "Access_Error"=>4,
133 # Cannot compile header files
134 "Cannot_Compile"=>5,
135 # Header compiled with errors
136 "Compile_Error"=>6,
137 # Invalid input ABI dump
138 "Invalid_Dump"=>7,
139 # Incompatible version of ABI dump
140 "Dump_Version"=>8,
141 # Cannot find a module
142 "Module_Error"=>9,
143 # Empty intersection between
144 # headers and shared objects
145 "Empty_Intersection"=>10,
146 # Empty set of symbols in headers
147 "Empty_Set"=>11
148);
149
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300150my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400151
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400152my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400153A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300154Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400155License: GNU LGPL or GNU GPL
156
157Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400158Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400159
160OLD.xml and NEW.xml are XML-descriptors:
161
162 <version>
163 1.0
164 </version>
165
166 <headers>
167 /path/to/headers/
168 </headers>
169
170 <libs>
171 /path/to/libraries/
172 </libs>
173
174More info: $CmdName --help\n";
175
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400176if($#ARGV==-1)
177{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400178 printMsg("INFO", $ShortUsage);
179 exit(0);
180}
181
182foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400183{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400184 if($ARGV[$_-1] eq ",")
185 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400186 $ARGV[$_-2].=",".$ARGV[$_];
187 splice(@ARGV, $_-1, 2);
188 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400189 elsif($ARGV[$_-1]=~/,\Z/)
190 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400191 $ARGV[$_-1].=$ARGV[$_];
192 splice(@ARGV, $_, 1);
193 }
194 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400195 and $ARGV[$_] ne ",")
196 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400197 $ARGV[$_-1].=$ARGV[$_];
198 splice(@ARGV, $_, 1);
199 }
200}
201
202GetOptions("h|help!" => \$Help,
203 "i|info!" => \$InfoMsg,
204 "v|version!" => \$ShowVersion,
205 "dumpversion!" => \$DumpVersion,
206# general options
207 "l|lib|library=s" => \$TargetLibraryName,
208 "d1|old|o=s" => \$Descriptor{1}{"Path"},
209 "d2|new|n=s" => \$Descriptor{2}{"Path"},
210 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
211 "old-dumps!" => \$UseOldDumps,
212# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400213 "app|application=s" => \$AppPath,
214 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400215 "gcc-path|cross-gcc=s" => \$CrossGcc,
216 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
217 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400218 "sysroot=s" => \$SystemRoot_Opt,
219 "v1|version1|vnum=s" => \$TargetVersion{1},
220 "v2|version2=s" => \$TargetVersion{2},
221 "s|strict!" => \$StrictCompat,
222 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300223 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400224 "skip-symbols=s" => \$SkipSymbolsListPath,
225 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400226 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400227 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400228 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
229 "objects-only!" => \$CheckObjectsOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "show-retval!" => \$ShowRetVal,
231 "use-dumps!" => \$UseDumps,
232 "nostdinc!" => \$NoStdInc,
233 "dump-system=s" => \$DumpSystem,
234 "sysinfo=s" => \$TargetSysInfo,
235 "cmp-systems!" => \$CmpSystems,
236 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400237 "ext|extended!" => \$ExtendedCheck,
238 "q|quiet!" => \$Quiet,
239 "stdout!" => \$StdOut,
240 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400241 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400242 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400243 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400244 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400245 "binary|bin|abi!" => \$BinaryOnly,
246 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400247 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400248# other options
249 "test!" => \$TestTool,
250 "test-dump!" => \$TestDump,
251 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400252 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400253 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400254 "p|params=s" => \$ParamNamesPath,
255 "relpath1|relpath=s" => \$RelativeDirectory{1},
256 "relpath2=s" => \$RelativeDirectory{2},
257 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400258 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400259 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400260 "bin-report-path=s" => \$BinaryReportPath,
261 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400262 "log-path=s" => \$LoggingPath,
263 "log1-path=s" => \$OutputLogPath{1},
264 "log2-path=s" => \$OutputLogPath{2},
265 "logging-mode=s" => \$LogMode,
266 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300267 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400268 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400269 "extra-info=s" => \$ExtraInfo,
270 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400271 "force!" => \$Force,
272 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400273 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400274 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400275 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400276 "all-affected!" => \$AllAffected,
277 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400278) or ERR_MESSAGE();
279
280sub ERR_MESSAGE()
281{
282 printMsg("INFO", "\n".$ShortUsage);
283 exit($ERROR_CODE{"Error"});
284}
285
286my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
287my $SLIB_TYPE = $LIB_TYPE;
288if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
289{ # show as "shared" library
290 $SLIB_TYPE = "shared";
291}
292my $LIB_EXT = getLIB_EXT($OSgroup);
293my $AR_EXT = getAR_EXT($OSgroup);
294my $BYTE_SIZE = 8;
295my $COMMON_LOG_PATH = "logs/run.log";
296
297my $HelpMessage="
298NAME:
299 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400300 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400301
302DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400303 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400304 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
305 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
306 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
307 and/or source-level compatibility: changes in calling stack, v-table changes,
308 removed symbols, renamed fields, etc. Binary incompatibility may result in
309 crashing or incorrect behavior of applications built with an old version of
310 a library if they run on a new one. Source incompatibility may result in
311 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400312
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400313 The tool is intended for developers of software libraries and maintainers
314 of operating systems who are interested in ensuring backward compatibility,
315 i.e. allow old applications to run or to be recompiled with newer library
316 versions.
317
318 Also the tool can be used by ISVs for checking applications portability to
319 new library versions. Found issues can be taken into account when adapting
320 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400321
322 This tool is free software: you can redistribute it and/or modify it
323 under the terms of the GNU LGPL or GNU GPL.
324
325USAGE:
326 $CmdName [options]
327
328EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400329 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400330
331 OLD.xml and NEW.xml are XML-descriptors:
332
333 <version>
334 1.0
335 </version>
336
337 <headers>
338 /path1/to/header(s)/
339 /path2/to/header(s)/
340 ...
341 </headers>
342
343 <libs>
344 /path1/to/library(ies)/
345 /path2/to/library(ies)/
346 ...
347 </libs>
348
349INFORMATION OPTIONS:
350 -h|-help
351 Print this help.
352
353 -i|-info
354 Print complete info.
355
356 -v|-version
357 Print version information.
358
359 -dumpversion
360 Print the tool version ($TOOL_VERSION) and don't do anything else.
361
362GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400363 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400364 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400365
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400366 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367 Descriptor of 1st (old) library version.
368 It may be one of the following:
369
370 1. XML-descriptor (VERSION.xml file):
371
372 <version>
373 1.0
374 </version>
375
376 <headers>
377 /path1/to/header(s)/
378 /path2/to/header(s)/
379 ...
380 </headers>
381
382 <libs>
383 /path1/to/library(ies)/
384 /path2/to/library(ies)/
385 ...
386 </libs>
387
388 ... (XML-descriptor template
389 can be generated by -d option)
390
391 2. ABI dump generated by -dump option
392 3. Directory with headers and/or $SLIB_TYPE libraries
393 4. Single header file
394 5. Single $SLIB_TYPE library
395 6. Comma separated list of headers and/or libraries
396
397 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400398 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400399
400 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400401 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400403 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400404 Descriptor of 2nd (new) library version.
405
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400406 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400407 Create library ABI dump for the input XML descriptor. You can
408 transfer it anywhere and pass instead of the descriptor. Also
409 it can be used for debugging the tool.
410
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400411 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400412
413 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400414 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415
416sub HELP_MESSAGE() {
417 printMsg("INFO", $HelpMessage."
418MORE INFO:
419 $CmdName --info\n");
420}
421
422sub INFO_MESSAGE()
423{
424 printMsg("INFO", "$HelpMessage
425EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400426 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300427 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400428 for portability to the new library version.
429
430 -static-libs
431 Check static libraries instead of the shared ones. The <libs> section
432 of the XML-descriptor should point to static libraries location.
433
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400434 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 Path to the cross GCC compiler to use instead of the usual (host) GCC.
436
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400437 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400438 GCC toolchain prefix.
439
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400440 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400441 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400442 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400443
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400444 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400445 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200446 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400447
448 In general case you should specify it in the XML-descriptor:
449 <version>
450 VERSION
451 </version>
452
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400453 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400454 Specify 2nd library version outside the descriptor.
455
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400456 -vnum NUM
457 Specify the library version in the generated ABI dump. The <version> section
458 of the input XML descriptor will be overwritten in this case.
459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400460 -s|-strict
461 Treat all compatibility warnings as problems. Add a number of \"Low\"
462 severity problems to the return value of the tool.
463
464 -headers-only
465 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
466 provide a low quality compatibility report with false positives and
467 without detecting of added/removed symbols.
468
469 Alternatively you can write \"none\" word to the <libs> section
470 in the XML-descriptor:
471 <libs>
472 none
473 </libs>
474
475 -objects-only
476 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
477 provide a low quality compatibility report with false positives and
478 without analysis of changes in parameters and data types.
479
480 Alternatively you can write \"none\" word to the <headers> section
481 in the XML-descriptor:
482 <headers>
483 none
484 </headers>
485
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400486 -show-retval
487 Show the symbol's return type in the report.
488
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400489 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300490 This option allows to specify a file with a list of symbols (mangled
491 names in C++) that should be checked. Other symbols will not be checked.
492
493 -types-list PATH
494 This option allows to specify a file with a list of types that should
495 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400496
497 -skip-symbols PATH
498 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400500 -headers-list PATH
501 The file with a list of headers, that should be checked/dumped.
502
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400503 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400504 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400505
506 -header NAME
507 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400508
509 -use-dumps
510 Make dumps for two versions of a library and compare dumps. This should
511 increase the performance of the tool and decrease the system memory usage.
512
513 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400514 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400515
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400516 -dump-system NAME -sysroot DIR
517 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518 create XML descriptors and make ABI dumps for each library. The result
519 set of ABI dumps can be compared (--cmp-systems) with the other one
520 created for other version of operating system in order to check them for
521 compatibility. Do not forget to specify -cross-gcc option if your target
522 system requires some specific version of GCC compiler (different from
523 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400524 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400525
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400526 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400527 The same as the previous option but takes an XML descriptor of the target
528 system as input, where you should describe it:
529
530 /* Primary sections */
531
532 <name>
533 /* Name of the system */
534 </name>
535
536 <headers>
537 /* The list of paths to header files and/or
538 directories with header files, one per line */
539 </headers>
540
541 <libs>
542 /* The list of paths to shared libraries and/or
543 directories with shared libraries, one per line */
544 </libs>
545
546 /* Optional sections */
547
548 <search_headers>
549 /* List of directories to be searched
550 for header files to automatically
551 generate include paths, one per line */
552 </search_headers>
553
554 <search_libs>
555 /* List of directories to be searched
556 for shared libraries to resolve
557 dependencies, one per line */
558 </search_libs>
559
560 <tools>
561 /* List of directories with tools used
562 for analysis (GCC toolchain), one per line */
563 </tools>
564
565 <cross_prefix>
566 /* GCC toolchain prefix.
567 Examples:
568 arm-linux-gnueabi
569 arm-none-symbianelf */
570 </cross_prefix>
571
572 <gcc_options>
573 /* Additional GCC options, one per line */
574 </gcc_options>
575
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400576 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300577 This option should be used with -dump-system option to dump
578 ABI of operating systems and configure the dumping process.
579 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400580 modules/Targets/{unix, symbian, windows}
581
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400582 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583 Compare two system ABI dumps. Create compatibility reports for each
584 library and the common HTML report including the summary of test
585 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400586 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400587
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400588 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400589 The file with a list of libraries, that should be dumped by
590 the -dump-system option or should be checked by the -cmp-systems option.
591
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400592 -ext|-extended
593 If your library A is supposed to be used by other library B and you
594 want to control the ABI of B, then you should enable this option. The
595 tool will check for changes in all data types, even if they are not
596 used by any function in the library A. Such data types are not part
597 of the A library ABI, but may be a part of the ABI of the B library.
598
599 The short scheme is:
600 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
601
602 -q|-quiet
603 Print all messages to the file instead of stdout and stderr.
604 Default path (can be changed by -log-path option):
605 $COMMON_LOG_PATH
606
607 -stdout
608 Print analysis results (compatibility reports and ABI dumps) to stdout
609 instead of creating a file. This would allow piping data to other programs.
610
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400611 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400612 Change format of compatibility report.
613 Formats:
614 htm - HTML format (default)
615 xml - XML format
616
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400617 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400618 Change format of ABI dump.
619 Formats:
620 perl - Data::Dumper format (default)
621 xml - XML format
622
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400623 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400624 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400625
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400626 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400627 Set library language (C or C++). You can use this option if the tool
628 cannot auto-detect a language. This option may be useful for checking
629 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400630
631 -arch ARCH
632 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
633 ect.). The option is useful if the tool cannot detect correct architecture
634 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400635
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400636 -binary|-bin|-abi
637 Show \"Binary\" compatibility problems only.
638 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400639 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400640
641 -source|-src|-api
642 Show \"Source\" compatibility problems only.
643 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400644 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400645
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400646 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400647 The maximum number of affected symbols listed under the description
648 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400649
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400650OTHER OPTIONS:
651 -test
652 Run internal tests. Create two binary incompatible versions of a sample
653 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300654 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400655
656 -test-dump
657 Test ability to create, read and compare ABI dumps.
658
659 -debug
660 Debugging mode. Print debug info on the screen. Save intermediate
661 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400664 Also consider using --dump option for debugging the tool.
665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400666 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 If your header files are written in C language and can be compiled
668 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
669 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400670
671 -cpp-incompatible
672 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400675 Path to file with the function parameter names. It can be used
676 for improving report view if the library header files have no
677 parameter names. File format:
678
679 func1;param1;param2;param3 ...
680 func2;param1;param2;param3 ...
681 ...
682
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 -relpath PATH
684 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400685 for dumping the library ABI (see -dump option).
686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -relpath1 PATH
688 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -relpath2 PATH
691 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400694 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400698 -sort
699 Enable sorting of data in ABI dumps.
700
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400701 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400702 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400703 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400704 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400705
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400706 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400707 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400708 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400709 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400710
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400711 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400712 Path to \"Source\" compatibility report.
713 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400715
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400717 Log path for all messages.
718 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400719 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400721 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400722 Log path for 1st version of a library.
723 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400724 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400725
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400726 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400727 Log path for 2nd version of a library.
728 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400729 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400730
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400732 Change logging mode.
733 Modes:
734 w - overwrite old logs (default)
735 a - append old logs
736 n - do not write any logs
737
738 -list-affected
739 Generate file with the list of incompatible
740 symbols beside the HTML compatibility report.
741 Use 'c++filt \@file' command from GNU binutils
742 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400743 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400744 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400745 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400746
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400747 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400748 The component name in the title and summary of the HTML report.
749 Default:
750 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300751
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300752 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400753 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400754 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400755
756 -extra-info DIR
757 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400758
759 -extra-dump
760 Create extended ABI dump containing all symbols
761 from the translation unit.
762
763 -force
764 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400765
766 -tolerance LEVEL
767 Apply a set of heuristics to successfully compile input
768 header files. You can enable several tolerance levels by
769 joining them into one string (e.g. 13, 124, etc.).
770 Levels:
771 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
772 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
773 3 - skip headers that iclude non-Linux headers
774 4 - skip headers included by others
775
776 -tolerant
777 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400778
779 -check
780 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400781
782 -quick
783 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400784
785 -skip-internal PATTERN
786 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400788REPORT:
789 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400790 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400791
792 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400793 logs/LIB_NAME/V1/log.txt
794 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400795
796EXIT CODES:
797 0 - Compatible. The tool has run without any errors.
798 non-zero - Incompatible or the tool has run with errors.
799
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400800MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300801 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400802}
803
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400804my %Operator_Indication = (
805 "not" => "~",
806 "assign" => "=",
807 "andassign" => "&=",
808 "orassign" => "|=",
809 "xorassign" => "^=",
810 "or" => "|",
811 "xor" => "^",
812 "addr" => "&",
813 "and" => "&",
814 "lnot" => "!",
815 "eq" => "==",
816 "ne" => "!=",
817 "lt" => "<",
818 "lshift" => "<<",
819 "lshiftassign" => "<<=",
820 "rshiftassign" => ">>=",
821 "call" => "()",
822 "mod" => "%",
823 "modassign" => "%=",
824 "subs" => "[]",
825 "land" => "&&",
826 "lor" => "||",
827 "rshift" => ">>",
828 "ref" => "->",
829 "le" => "<=",
830 "deref" => "*",
831 "mult" => "*",
832 "preinc" => "++",
833 "delete" => " delete",
834 "vecnew" => " new[]",
835 "vecdelete" => " delete[]",
836 "predec" => "--",
837 "postinc" => "++",
838 "postdec" => "--",
839 "plusassign" => "+=",
840 "plus" => "+",
841 "minus" => "-",
842 "minusassign" => "-=",
843 "gt" => ">",
844 "ge" => ">=",
845 "new" => " new",
846 "multassign" => "*=",
847 "divassign" => "/=",
848 "div" => "/",
849 "neg" => "-",
850 "pos" => "+",
851 "memref" => "->*",
852 "compound" => "," );
853
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400854my %UnknownOperator;
855
856my %NodeType= (
857 "array_type" => "Array",
858 "binfo" => "Other",
859 "boolean_type" => "Intrinsic",
860 "complex_type" => "Intrinsic",
861 "const_decl" => "Other",
862 "enumeral_type" => "Enum",
863 "field_decl" => "Other",
864 "function_decl" => "Other",
865 "function_type" => "FunctionType",
866 "identifier_node" => "Other",
867 "integer_cst" => "Other",
868 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400869 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400870 "method_type" => "MethodType",
871 "namespace_decl" => "Other",
872 "parm_decl" => "Other",
873 "pointer_type" => "Pointer",
874 "real_cst" => "Other",
875 "real_type" => "Intrinsic",
876 "record_type" => "Struct",
877 "reference_type" => "Ref",
878 "string_cst" => "Other",
879 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400880 "template_type_parm" => "TemplateParam",
881 "typename_type" => "TypeName",
882 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400883 "tree_list" => "Other",
884 "tree_vec" => "Other",
885 "type_decl" => "Other",
886 "union_type" => "Union",
887 "var_decl" => "Other",
888 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400889 "nop_expr" => "Other", #
890 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400891 "offset_type" => "Other" );
892
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400893my %CppKeywords_C = map {$_=>1} (
894 # C++ 2003 keywords
895 "public",
896 "protected",
897 "private",
898 "default",
899 "template",
900 "new",
901 #"asm",
902 "dynamic_cast",
903 "auto",
904 "try",
905 "namespace",
906 "typename",
907 "using",
908 "reinterpret_cast",
909 "friend",
910 "class",
911 "virtual",
912 "const_cast",
913 "mutable",
914 "static_cast",
915 "export",
916 # C++0x keywords
917 "noexcept",
918 "nullptr",
919 "constexpr",
920 "static_assert",
921 "explicit",
922 # cannot be used as a macro name
923 # as it is an operator in C++
924 "and",
925 #"and_eq",
926 "not",
927 #"not_eq",
928 "or"
929 #"or_eq",
930 #"bitand",
931 #"bitor",
932 #"xor",
933 #"xor_eq",
934 #"compl"
935);
936
937my %CppKeywords_F = map {$_=>1} (
938 "delete",
939 "catch",
940 "alignof",
941 "thread_local",
942 "decltype",
943 "typeid"
944);
945
946my %CppKeywords_O = map {$_=>1} (
947 "bool",
948 "register",
949 "inline",
950 "operator"
951);
952
953my %CppKeywords_A = map {$_=>1} (
954 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400955 "throw",
956 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400957);
958
959foreach (keys(%CppKeywords_C),
960keys(%CppKeywords_F),
961keys(%CppKeywords_O)) {
962 $CppKeywords_A{$_}=1;
963}
964
965# Header file extensions as described by gcc
966my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
967
968my %IntrinsicMangling = (
969 "void" => "v",
970 "bool" => "b",
971 "wchar_t" => "w",
972 "char" => "c",
973 "signed char" => "a",
974 "unsigned char" => "h",
975 "short" => "s",
976 "unsigned short" => "t",
977 "int" => "i",
978 "unsigned int" => "j",
979 "long" => "l",
980 "unsigned long" => "m",
981 "long long" => "x",
982 "__int64" => "x",
983 "unsigned long long" => "y",
984 "__int128" => "n",
985 "unsigned __int128" => "o",
986 "float" => "f",
987 "double" => "d",
988 "long double" => "e",
989 "__float80" => "e",
990 "__float128" => "g",
991 "..." => "z"
992);
993
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400994my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400996my %StdcxxMangling = (
997 "3std"=>"St",
998 "3std9allocator"=>"Sa",
999 "3std12basic_string"=>"Sb",
1000 "3std12basic_stringIcE"=>"Ss",
1001 "3std13basic_istreamIcE"=>"Si",
1002 "3std13basic_ostreamIcE"=>"So",
1003 "3std14basic_iostreamIcE"=>"Sd"
1004);
1005
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001006my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001007my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1008
1009my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001010my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001011
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001012my %ConstantSuffix = (
1013 "unsigned int"=>"u",
1014 "long"=>"l",
1015 "unsigned long"=>"ul",
1016 "long long"=>"ll",
1017 "unsigned long long"=>"ull"
1018);
1019
1020my %ConstantSuffixR =
1021reverse(%ConstantSuffix);
1022
1023my %OperatorMangling = (
1024 "~" => "co",
1025 "=" => "aS",
1026 "|" => "or",
1027 "^" => "eo",
1028 "&" => "an",#ad (addr)
1029 "==" => "eq",
1030 "!" => "nt",
1031 "!=" => "ne",
1032 "<" => "lt",
1033 "<=" => "le",
1034 "<<" => "ls",
1035 "<<=" => "lS",
1036 ">" => "gt",
1037 ">=" => "ge",
1038 ">>" => "rs",
1039 ">>=" => "rS",
1040 "()" => "cl",
1041 "%" => "rm",
1042 "[]" => "ix",
1043 "&&" => "aa",
1044 "||" => "oo",
1045 "*" => "ml",#de (deref)
1046 "++" => "pp",#
1047 "--" => "mm",#
1048 "new" => "nw",
1049 "delete" => "dl",
1050 "new[]" => "na",
1051 "delete[]" => "da",
1052 "+=" => "pL",
1053 "+" => "pl",#ps (pos)
1054 "-" => "mi",#ng (neg)
1055 "-=" => "mI",
1056 "*=" => "mL",
1057 "/=" => "dV",
1058 "&=" => "aN",
1059 "|=" => "oR",
1060 "%=" => "rM",
1061 "^=" => "eO",
1062 "/" => "dv",
1063 "->*" => "pm",
1064 "->" => "pt",#rf (ref)
1065 "," => "cm",
1066 "?" => "qu",
1067 "." => "dt",
1068 "sizeof"=> "sz"#st
1069);
1070
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001071my %Intrinsic_Keywords = map {$_=>1} (
1072 "true",
1073 "false",
1074 "_Bool",
1075 "_Complex",
1076 "const",
1077 "int",
1078 "long",
1079 "void",
1080 "short",
1081 "float",
1082 "volatile",
1083 "restrict",
1084 "unsigned",
1085 "signed",
1086 "char",
1087 "double",
1088 "class",
1089 "struct",
1090 "union",
1091 "enum"
1092);
1093
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001094my %GlibcHeader = map {$_=>1} (
1095 "aliases.h",
1096 "argp.h",
1097 "argz.h",
1098 "assert.h",
1099 "cpio.h",
1100 "ctype.h",
1101 "dirent.h",
1102 "envz.h",
1103 "errno.h",
1104 "error.h",
1105 "execinfo.h",
1106 "fcntl.h",
1107 "fstab.h",
1108 "ftw.h",
1109 "glob.h",
1110 "grp.h",
1111 "iconv.h",
1112 "ifaddrs.h",
1113 "inttypes.h",
1114 "langinfo.h",
1115 "limits.h",
1116 "link.h",
1117 "locale.h",
1118 "malloc.h",
1119 "math.h",
1120 "mntent.h",
1121 "monetary.h",
1122 "nl_types.h",
1123 "obstack.h",
1124 "printf.h",
1125 "pwd.h",
1126 "regex.h",
1127 "sched.h",
1128 "search.h",
1129 "setjmp.h",
1130 "shadow.h",
1131 "signal.h",
1132 "spawn.h",
1133 "stdarg.h",
1134 "stdint.h",
1135 "stdio.h",
1136 "stdlib.h",
1137 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001138 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001139 "tar.h",
1140 "termios.h",
1141 "time.h",
1142 "ulimit.h",
1143 "unistd.h",
1144 "utime.h",
1145 "wchar.h",
1146 "wctype.h",
1147 "wordexp.h" );
1148
1149my %GlibcDir = map {$_=>1} (
1150 "arpa",
1151 "bits",
1152 "gnu",
1153 "netinet",
1154 "net",
1155 "nfs",
1156 "rpc",
1157 "sys",
1158 "linux" );
1159
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001160my %WinHeaders = map {$_=>1} (
1161 "dos.h",
1162 "process.h",
1163 "winsock.h",
1164 "config-win.h",
1165 "mem.h",
1166 "windows.h",
1167 "winsock2.h",
1168 "crtdbg.h",
1169 "ws2tcpip.h"
1170);
1171
1172my %ObsoleteHeaders = map {$_=>1} (
1173 "iostream.h",
1174 "fstream.h"
1175);
1176
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001177my %AlienHeaders = map {$_=>1} (
1178 # Solaris
1179 "thread.h",
1180 "sys/atomic.h",
1181 # HPUX
1182 "sys/stream.h",
1183 # Symbian
1184 "AknDoc.h",
1185 # Atari ST
1186 "ext.h",
1187 "tos.h",
1188 # MS-DOS
1189 "alloc.h",
1190 # Sparc
1191 "sys/atomic.h"
1192);
1193
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001194my %ConfHeaders = map {$_=>1} (
1195 "atomic",
1196 "conf.h",
1197 "config.h",
1198 "configure.h",
1199 "build.h",
1200 "setup.h"
1201);
1202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001203my %LocalIncludes = map {$_=>1} (
1204 "/usr/local/include",
1205 "/usr/local" );
1206
1207my %OS_AddPath=(
1208# These paths are needed if the tool cannot detect them automatically
1209 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001210 "include"=>[
1211 "/Library",
1212 "/Developer/usr/include"
1213 ],
1214 "lib"=>[
1215 "/Library",
1216 "/Developer/usr/lib"
1217 ],
1218 "bin"=>[
1219 "/Developer/usr/bin"
1220 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001221 },
1222 "beos"=>{
1223 # Haiku has GCC 2.95.3 by default
1224 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001225 "include"=>[
1226 "/boot/common",
1227 "/boot/develop"
1228 ],
1229 "lib"=>[
1230 "/boot/common/lib",
1231 "/boot/system/lib",
1232 "/boot/apps"
1233 ],
1234 "bin"=>[
1235 "/boot/common/bin",
1236 "/boot/system/bin",
1237 "/boot/develop/abi"
1238 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001240);
1241
1242my %Slash_Type=(
1243 "default"=>"/",
1244 "windows"=>"\\"
1245);
1246
1247my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1248
1249# Global Variables
1250my %COMMON_LANGUAGE=(
1251 1 => "C",
1252 2 => "C" );
1253
1254my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001255my $MAX_CPPFILT_FILE_SIZE = 50000;
1256my $CPPFILT_SUPPORT_FILE;
1257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001258my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1259
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001260my $STDCXX_TESTING = 0;
1261my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001262my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001263
1264my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1265my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001266
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001267my $TargetComponent;
1268
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001269my $CheckUndefined = 0;
1270
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001271# Set Target Component Name
1272if($TargetComponent_Opt) {
1273 $TargetComponent = lc($TargetComponent_Opt);
1274}
1275else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001276{ # default: library
1277 # other components: header, system, ...
1278 $TargetComponent = "library";
1279}
1280
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001281my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001282
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001283my $SystemRoot;
1284
1285my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001286my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287my %LOG_PATH;
1288my %DEBUG_PATH;
1289my %Cache;
1290my %LibInfo;
1291my $COMPILE_ERRORS = 0;
1292my %CompilerOptions;
1293my %CheckedDyLib;
1294my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1295
1296# Constants (#defines)
1297my %Constants;
1298my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001299my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001301# Extra Info
1302my %SymbolHeader;
1303my %KnownLibs;
1304
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001305# Templates
1306my %TemplateInstance;
1307my %BasicTemplate;
1308my %TemplateArg;
1309my %TemplateDecl;
1310my %TemplateMap;
1311
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001312# Types
1313my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001314my %SkipTypes = (
1315 "1"=>{},
1316 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001317my %CheckedTypes;
1318my %TName_Tid;
1319my %EnumMembName_Id;
1320my %NestedNameSpaces = (
1321 "1"=>{},
1322 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001323my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001324my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001325my %ClassVTable;
1326my %ClassVTable_Content;
1327my %VTableClass;
1328my %AllocableClass;
1329my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001330my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001331my %Class_SubClasses;
1332my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001333my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001334my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001335
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001336my %CheckedTypeInfo;
1337
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001338# Typedefs
1339my %Typedef_BaseName;
1340my %Typedef_Tr;
1341my %Typedef_Eq;
1342my %StdCxxTypedef;
1343my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001344my %MissedBase;
1345my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001346my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001347
1348# Symbols
1349my %SymbolInfo;
1350my %tr_name;
1351my %mangled_name_gcc;
1352my %mangled_name;
1353my %SkipSymbols = (
1354 "1"=>{},
1355 "2"=>{} );
1356my %SkipNameSpaces = (
1357 "1"=>{},
1358 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001359my %AddNameSpaces = (
1360 "1"=>{},
1361 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001362my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001363my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001364my %SymbolsList_App;
1365my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001366my %Symbol_Library = (
1367 "1"=>{},
1368 "2"=>{} );
1369my %Library_Symbol = (
1370 "1"=>{},
1371 "2"=>{} );
1372my %DepSymbol_Library = (
1373 "1"=>{},
1374 "2"=>{} );
1375my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376 "1"=>{},
1377 "2"=>{} );
1378my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001379my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001380my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001381my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001382my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001383my %Library_Needed= (
1384 "1"=>{},
1385 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001386
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001387# Extra Info
1388my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001389my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001391# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001392my %Include_Preamble = (
1393 "1"=>[],
1394 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001395my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001396my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001397my %HeaderName_Paths;
1398my %Header_Dependency;
1399my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001400my %Include_Paths = (
1401 "1"=>[],
1402 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001403my %INC_PATH_AUTODETECT = (
1404 "1"=>1,
1405 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001406my %Add_Include_Paths = (
1407 "1"=>[],
1408 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409my %Skip_Include_Paths;
1410my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411my %Header_ErrorRedirect;
1412my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001413my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001414my %Header_ShouldNotBeUsed;
1415my %RecursiveIncludes;
1416my %Header_Include_Prefix;
1417my %SkipHeaders;
1418my %SkipHeadersList=(
1419 "1"=>{},
1420 "2"=>{} );
1421my %SkipLibs;
1422my %Include_Order;
1423my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001424my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001425my %TUnit_Funcs;
1426my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001427
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001428my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001429 "1"=>0,
1430 "2"=>0 );
1431my %AutoPreambleMode = (
1432 "1"=>0,
1433 "2"=>0 );
1434my %MinGWMode = (
1435 "1"=>0,
1436 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001437my %Cpp0xMode = (
1438 "1"=>0,
1439 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001440
1441# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001442my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001443my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001444my %RegisteredSONAMEs;
1445my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001447my %CheckedArch;
1448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001449# System Objects
1450my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001451my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001452my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001453
1454# System Headers
1455my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001456my @DefaultCppPaths;
1457my @DefaultGccPaths;
1458my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001459my %DefaultCppHeader;
1460my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001461my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001462
1463# Merging
1464my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001465my $Version;
1466my %AddedInt;
1467my %RemovedInt;
1468my %AddedInt_Virt;
1469my %RemovedInt_Virt;
1470my %VirtualReplacement;
1471my %ChangedTypedef;
1472my %CompatRules;
1473my %IncompleteRules;
1474my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001475my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001476my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001477my %ReturnedClass;
1478my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001479my %SourceAlternative;
1480my %SourceAlternative_B;
1481my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001482my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001483
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001484# Calling Conventions
1485my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001486 1=>{ "R"=>0, "P"=>0 },
1487 2=>{ "R"=>0, "P"=>0 }
1488);
1489
1490# ABI Dump
1491my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001492
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001493# OS Compliance
1494my %TargetLibs;
1495my %TargetHeaders;
1496
1497# OS Specifics
1498my $OStarget = $OSgroup;
1499my %TargetTools;
1500
1501# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001502my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001503
1504# Recursion locks
1505my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001507my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001508my @RecurInclude;
1509my @RecurConstant;
1510
1511# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001512my %SystemPaths = (
1513 "include"=>[],
1514 "lib"=>[],
1515 "bin"=>[]
1516);
1517my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001518my $GCC_PATH;
1519
1520# Symbols versioning
1521my %SymVer = (
1522 "1"=>{},
1523 "2"=>{} );
1524
1525# Problem descriptions
1526my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001527my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001528my %TotalAffected;
1529
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001530# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001531my $ContentID = 1;
1532my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1533my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1534my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1535my $ContentSpanEnd = "</span>\n";
1536my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1537my $ContentDivEnd = "</div>\n";
1538my $Content_Counter = 0;
1539
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001540# Modes
1541my $JoinReport = 1;
1542my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001543
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001544my %Severity_Val=(
1545 "High"=>3,
1546 "Medium"=>2,
1547 "Low"=>1,
1548 "Safe"=>-1
1549);
1550
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001551sub get_Modules()
1552{
1553 my $TOOL_DIR = get_dirname($0);
1554 if(not $TOOL_DIR)
1555 { # patch for MS Windows
1556 $TOOL_DIR = ".";
1557 }
1558 my @SEARCH_DIRS = (
1559 # tool's directory
1560 abs_path($TOOL_DIR),
1561 # relative path to modules
1562 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001563 # install path
1564 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001565 );
1566 foreach my $DIR (@SEARCH_DIRS)
1567 {
1568 if(not is_abs($DIR))
1569 { # relative path
1570 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1571 }
1572 if(-d $DIR."/modules") {
1573 return $DIR."/modules";
1574 }
1575 }
1576 exitStatus("Module_Error", "can't find modules");
1577}
1578
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001579my %LoadedModules = ();
1580
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001581sub loadModule($)
1582{
1583 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001584 if(defined $LoadedModules{$Name}) {
1585 return;
1586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001587 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1588 if(not -f $Path) {
1589 exitStatus("Module_Error", "can't access \'$Path\'");
1590 }
1591 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001592 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001593}
1594
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001595sub readModule($$)
1596{
1597 my ($Module, $Name) = @_;
1598 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1599 if(not -f $Path) {
1600 exitStatus("Module_Error", "can't access \'$Path\'");
1601 }
1602 return readFile($Path);
1603}
1604
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001605sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001606{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001607 my $Number = $_[0];
1608 if(not $Number) {
1609 $Number = 1;
1610 }
1611 else {
1612 $Number = int($Number)+1;
1613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001614 if($Number>3) {
1615 return $Number."th";
1616 }
1617 elsif($Number==1) {
1618 return "1st";
1619 }
1620 elsif($Number==2) {
1621 return "2nd";
1622 }
1623 elsif($Number==3) {
1624 return "3rd";
1625 }
1626 else {
1627 return $Number;
1628 }
1629}
1630
1631sub search_Tools($)
1632{
1633 my $Name = $_[0];
1634 return "" if(not $Name);
1635 if(my @Paths = keys(%TargetTools))
1636 {
1637 foreach my $Path (@Paths)
1638 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001639 if(-f join_P($Path, $Name)) {
1640 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001641 }
1642 if($CrossPrefix)
1643 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001644 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001645 if(-f $Candidate) {
1646 return $Candidate;
1647 }
1648 }
1649 }
1650 }
1651 else {
1652 return "";
1653 }
1654}
1655
1656sub synch_Cmd($)
1657{
1658 my $Name = $_[0];
1659 if(not $GCC_PATH)
1660 { # GCC was not found yet
1661 return "";
1662 }
1663 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001664 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001665 return $Candidate;
1666 }
1667 return "";
1668}
1669
1670sub get_CmdPath($)
1671{
1672 my $Name = $_[0];
1673 return "" if(not $Name);
1674 if(defined $Cache{"get_CmdPath"}{$Name}) {
1675 return $Cache{"get_CmdPath"}{$Name};
1676 }
1677 my %BinUtils = map {$_=>1} (
1678 "c++filt",
1679 "objdump",
1680 "readelf"
1681 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001682 if($BinUtils{$Name} and $GCC_PATH)
1683 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001684 if(my $Dir = get_dirname($GCC_PATH)) {
1685 $TargetTools{$Dir}=1;
1686 }
1687 }
1688 my $Path = search_Tools($Name);
1689 if(not $Path and $OSgroup eq "windows") {
1690 $Path = search_Tools($Name.".exe");
1691 }
1692 if(not $Path and $BinUtils{$Name})
1693 {
1694 if($CrossPrefix)
1695 { # user-defined prefix
1696 $Path = search_Cmd($CrossPrefix."-".$Name);
1697 }
1698 }
1699 if(not $Path and $BinUtils{$Name})
1700 {
1701 if(my $Candidate = synch_Cmd($Name))
1702 { # synch with GCC
1703 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001704 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001705 if(-f $Candidate) {
1706 $Path = $Candidate;
1707 }
1708 }
1709 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001710 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001711 $Path = $Candidate;
1712 }
1713 }
1714 }
1715 if(not $Path) {
1716 $Path = search_Cmd($Name);
1717 }
1718 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001719 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001720 $Path=search_Cmd($Name.".exe");
1721 }
1722 if($Path=~/\s/) {
1723 $Path = "\"".$Path."\"";
1724 }
1725 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1726}
1727
1728sub search_Cmd($)
1729{
1730 my $Name = $_[0];
1731 return "" if(not $Name);
1732 if(defined $Cache{"search_Cmd"}{$Name}) {
1733 return $Cache{"search_Cmd"}{$Name};
1734 }
1735 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1736 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1737 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001738 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001739 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001740 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001741 if(-f $CmdPath)
1742 {
1743 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001744 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001745 }
1746 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1747 }
1748 }
1749 return ($Cache{"search_Cmd"}{$Name} = "");
1750}
1751
1752sub get_CmdPath_Default($)
1753{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001754 return "" if(not $_[0]);
1755 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1756 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001757 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001758 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1759}
1760
1761sub get_CmdPath_Default_I($)
1762{ # search in PATH
1763 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001764 if($Name=~/find/)
1765 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001766 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001767 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001768 }
1769 }
1770 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001771 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001772 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001773 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001774 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001776 if($OSgroup eq "windows")
1777 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001778 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001779 return $Name;
1780 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001781 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001782 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001783 {
1784 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001785 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001786 }
1787 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001788 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001789}
1790
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001791sub classifyPath($)
1792{
1793 my $Path = $_[0];
1794 if($Path=~/[\*\[]/)
1795 { # wildcard
1796 $Path=~s/\*/.*/g;
1797 $Path=~s/\\/\\\\/g;
1798 return ($Path, "Pattern");
1799 }
1800 elsif($Path=~/[\/\\]/)
1801 { # directory or relative path
1802 return (path_format($Path, $OSgroup), "Path");
1803 }
1804 else {
1805 return ($Path, "Name");
1806 }
1807}
1808
1809sub readDescriptor($$)
1810{
1811 my ($LibVersion, $Content) = @_;
1812 return if(not $LibVersion);
1813 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1814 if(not $Content) {
1815 exitStatus("Error", "$DName is empty");
1816 }
1817 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001818 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001819 }
1820 $Content=~s/\/\*(.|\n)+?\*\///g;
1821 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001823 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1824 if($TargetVersion{$LibVersion}) {
1825 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1826 }
1827 if(not $Descriptor{$LibVersion}{"Version"}) {
1828 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1829 }
1830 if($Content=~/{RELPATH}/)
1831 {
1832 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1833 $Content =~ s/{RELPATH}/$RelDir/g;
1834 }
1835 else
1836 {
1837 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1838 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1839 }
1840 }
1841
1842 if(not $CheckObjectsOnly_Opt)
1843 {
1844 my $DHeaders = parseTag(\$Content, "headers");
1845 if(not $DHeaders) {
1846 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1847 }
1848 elsif(lc($DHeaders) ne "none")
1849 { # append the descriptor headers list
1850 if($Descriptor{$LibVersion}{"Headers"})
1851 { # multiple descriptors
1852 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1853 }
1854 else {
1855 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1856 }
1857 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1858 {
1859 if(not -e $Path) {
1860 exitStatus("Access_Error", "can't access \'$Path\'");
1861 }
1862 }
1863 }
1864 }
1865 if(not $CheckHeadersOnly_Opt)
1866 {
1867 my $DObjects = parseTag(\$Content, "libs");
1868 if(not $DObjects) {
1869 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1870 }
1871 elsif(lc($DObjects) ne "none")
1872 { # append the descriptor libraries list
1873 if($Descriptor{$LibVersion}{"Libs"})
1874 { # multiple descriptors
1875 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1876 }
1877 else {
1878 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1879 }
1880 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1881 {
1882 if(not -e $Path) {
1883 exitStatus("Access_Error", "can't access \'$Path\'");
1884 }
1885 }
1886 }
1887 }
1888 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1889 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 if(not -d $Path) {
1891 exitStatus("Access_Error", "can't access directory \'$Path\'");
1892 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001893 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001895 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 }
1897 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1898 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001899 if(not -d $Path) {
1900 exitStatus("Access_Error", "can't access directory \'$Path\'");
1901 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001902 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001903 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001904 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001905 }
1906 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1907 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001908 if(not -d $Path) {
1909 exitStatus("Access_Error", "can't access directory \'$Path\'");
1910 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001911 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001912 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001913 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 $TargetTools{$Path}=1;
1915 }
1916 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1917 $CrossPrefix = $Prefix;
1918 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001919 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001920 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1921 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 if(not -d $Path) {
1923 exitStatus("Access_Error", "can't access directory \'$Path\'");
1924 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001925 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001927 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001928 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001929 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001930 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1931 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001932 if(not -d $Path) {
1933 exitStatus("Access_Error", "can't access directory \'$Path\'");
1934 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001935 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001937 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001938 }
1939 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001940 { # skip some auto-generated include paths
1941 if(not is_abs($Path))
1942 {
1943 if(my $P = abs_path($Path)) {
1944 $Path = $P;
1945 }
1946 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001947 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001948 }
1949 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001950 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001951 my ($CPath, $Type) = classifyPath($Path);
1952 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001953 }
1954 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001955 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1956 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001957 if($Option!~/\A\-(Wl|l|L)/)
1958 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001959 $CompilerOptions{$LibVersion} .= " ".$Option;
1960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001961 }
1962 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1963 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1964 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001965 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001966 my ($CPath, $Type) = classifyPath($Path);
1967 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001968 }
1969 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1970 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1971 {
1972 my ($CPath, $Type) = classifyPath($Path);
1973 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1974 }
1975 if(my $DDefines = parseTag(\$Content, "defines"))
1976 {
1977 if($Descriptor{$LibVersion}{"Defines"})
1978 { # multiple descriptors
1979 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1980 }
1981 else {
1982 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1983 }
1984 }
1985 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1986 {
1987 if($Order=~/\A(.+):(.+)\Z/) {
1988 $Include_Order{$LibVersion}{$1} = $2;
1989 }
1990 }
1991 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1992 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001993 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001994 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1995 }
1996 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1997 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001998 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001999 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2000 }
2001 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2002 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2003 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002004 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2005 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002007 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2008 $SkipConstants{$LibVersion}{$Constant} = 1;
2009 }
2010 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2011 {
2012 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002013 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002014 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2015 }
2016 else {
2017 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2018 }
2019 }
2020}
2021
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002022sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002023{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002024 my $CodeRef = shift(@_);
2025 my $Tag = shift(@_);
2026 if(not $Tag or not $CodeRef) {
2027 return undef;
2028 }
2029 my $Sp = 0;
2030 if(@_) {
2031 $Sp = shift(@_);
2032 }
2033 my $Start = index(${$CodeRef}, "<$Tag>");
2034 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002036 my $End = index(${$CodeRef}, "</$Tag>");
2037 if($End!=-1)
2038 {
2039 my $TS = length($Tag)+3;
2040 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2041 substr($Content, 0, $TS-1, ""); # cut start tag
2042 substr($Content, -$TS, $TS, ""); # cut end tag
2043 if(not $Sp)
2044 {
2045 $Content=~s/\A\s+//g;
2046 $Content=~s/\s+\Z//g;
2047 }
2048 if(substr($Content, 0, 1) ne "<") {
2049 $Content = xmlSpecChars_R($Content);
2050 }
2051 return $Content;
2052 }
2053 }
2054 return undef;
2055}
2056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002057sub getInfo($)
2058{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002059 my $DumpPath = $_[0];
2060 return if(not $DumpPath or not -f $DumpPath);
2061
2062 readTUDump($DumpPath);
2063
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002064 # processing info
2065 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002066
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002067 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002068 setAnonTypedef_All();
2069 }
2070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002071 getTypeInfo_All();
2072 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002073 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002074 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002075 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002076
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002077 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002078 %LibInfo = ();
2079 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002080 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002081 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002082 %TemplateDecl = ();
2083 %StdCxxTypedef = ();
2084 %MissedTypedef = ();
2085 %Typedef_Tr = ();
2086 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002087 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002088
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002089 # clean cache
2090 delete($Cache{"getTypeAttr"});
2091 delete($Cache{"getTypeDeclId"});
2092
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002093 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002094 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002095 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002096 }
2097 else
2098 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002099 if($BinaryOnly and not $ExtendedCheck)
2100 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002101 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002102 }
2103 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002104 remove_Unused($Version, "Extended");
2105 }
2106 }
2107
2108 if($CheckInfo)
2109 {
2110 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2111 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2112 }
2113
2114 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2115 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002116 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002117 }
2118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002119 if($Debug) {
2120 # debugMangling($Version);
2121 }
2122}
2123
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002124sub readTUDump($)
2125{
2126 my $DumpPath = $_[0];
2127
2128 open(TU_DUMP, $DumpPath);
2129 local $/ = undef;
2130 my $Content = <TU_DUMP>;
2131 close(TU_DUMP);
2132
2133 unlink($DumpPath);
2134
2135 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002136 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002137
2138 # clean memory
2139 undef $Content;
2140
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002141 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002142
2143 foreach (0 .. $#Lines)
2144 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002145 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002146 { # get a number and attributes of a node
2147 next if(not $NodeType{$2});
2148 $LibInfo{$Version}{"info_type"}{$1}=$2;
2149 $LibInfo{$Version}{"info"}{$1}=$3;
2150 }
2151
2152 # clean memory
2153 delete($Lines[$_]);
2154 }
2155
2156 # clean memory
2157 undef @Lines;
2158}
2159
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002160sub simplifyConstants()
2161{
2162 foreach my $Constant (keys(%{$Constants{$Version}}))
2163 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002164 if(defined $Constants{$Version}{$Constant}{"Header"})
2165 {
2166 my $Value = $Constants{$Version}{$Constant}{"Value"};
2167 if(defined $EnumConstants{$Version}{$Value}) {
2168 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2169 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002170 }
2171 }
2172}
2173
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002174sub simplifyNames()
2175{
2176 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2177 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002178 if($Typedef_Eq{$Version}{$Base}) {
2179 next;
2180 }
2181 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2182 if($#Translations==0)
2183 {
2184 if(length($Translations[0])<=length($Base)) {
2185 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2186 }
2187 }
2188 else
2189 { # select most appropriate
2190 foreach my $Tr (@Translations)
2191 {
2192 if($Base=~/\A\Q$Tr\E/)
2193 {
2194 $Typedef_Eq{$Version}{$Base} = $Tr;
2195 last;
2196 }
2197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002198 }
2199 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002200 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002201 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002202 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002203 if(not $TypeName) {
2204 next;
2205 }
2206 next if(index($TypeName,"<")==-1);# template instances only
2207 if($TypeName=~/>(::\w+)+\Z/)
2208 { # skip unused types
2209 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002210 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002211 foreach my $Base (sort {length($b)<=>length($a)}
2212 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002213 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002214 next if(not $Base);
2215 next if(index($TypeName,$Base)==-1);
2216 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002217 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002218 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002219 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2220 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2221 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002222 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002223 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2224 {
2225 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2226 {
2227 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2228 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002229 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002230 }
2231 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002234 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002235 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002236 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2237 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002238 }
2239}
2240
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002241sub setAnonTypedef_All()
2242{
2243 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2244 {
2245 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2246 {
2247 if(isAnon(getNameByInfo($InfoId))) {
2248 $TypedefToAnon{getTypeId($InfoId)} = 1;
2249 }
2250 }
2251 }
2252}
2253
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002254sub setTemplateParams_All()
2255{
2256 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2257 {
2258 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2259 setTemplateParams($_);
2260 }
2261 }
2262}
2263
2264sub setTemplateParams($)
2265{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002266 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002267 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002268 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002269 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002271 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002272 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002273 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002274 setTemplateInstParams($_[0], $TmplInst_Id);
2275 }
2276 }
2277
2278 $BasicTemplate{$Version}{$Tid} = $_[0];
2279
2280 if(my $Prms = getTreeAttr_Prms($_[0]))
2281 {
2282 if(my $Valu = getTreeAttr_Valu($Prms))
2283 {
2284 my $Vector = getTreeVec($Valu);
2285 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2286 {
2287 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2288 {
2289 if(my $Name = getNameByInfo($Val))
2290 {
2291 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2292 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2293 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2294 }
2295 else {
2296 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2297 }
2298 }
2299 }
2300 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002302 }
2303 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002304 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002305 {
2306 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2307 {
2308 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002309 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002310 }
2311 }
2312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002313}
2314
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002315sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002316{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002317 my ($Tmpl, $Inst) = @_;
2318
2319 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002320 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002321 my ($Params_InfoId, $ElemId) = ();
2322 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2323 $Params_InfoId = $1;
2324 }
2325 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2326 $ElemId = $1;
2327 }
2328 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002329 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002330 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2331 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2332 {
2333 my ($PPos, $PTypeId) = ($1, $2);
2334 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2335 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002336 if($PType eq "template_type_parm") {
2337 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002338 }
2339 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002340 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2341 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002342 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002343 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002344 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002345 else
2346 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002347 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002348 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002350 }
2351 }
2352 }
2353}
2354
2355sub getTypeDeclId($)
2356{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002357 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002358 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002359 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2360 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2361 }
2362 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2363 {
2364 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2365 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2366 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002369 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002370}
2371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002372sub getTypeInfo_All()
2373{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002374 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002375 { # support for GCC < 4.5
2376 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2377 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2378 # FIXME: check GCC versions
2379 addMissedTypes_Pre();
2380 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002381
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002382 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002383 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002384 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2385 if($IType=~/_type\Z/ and $IType ne "function_type"
2386 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002387 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002388 }
2389 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002390
2391 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002392 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002393 "Name" => "...",
2394 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002395 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002396 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002397 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002398
2399 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002400 { # support for GCC < 4.5
2401 addMissedTypes_Post();
2402 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002403
2404 if($ADD_TMPL_INSTANCES)
2405 {
2406 # templates
2407 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2408 {
2409 if(defined $TemplateMap{$Version}{$Tid}
2410 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2411 {
2412 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2413 {
2414 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2415 {
2416 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2417 {
2418 if(my %MAttr = getTypeAttr($MembTypeId))
2419 {
2420 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2421 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2422 }
2423 }
2424 }
2425 }
2426 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2427 {
2428 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2429 {
2430 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2431
2432 if($NBid ne $Bid)
2433 {
2434 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2435 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2436 }
2437 }
2438 }
2439 }
2440 }
2441 }
2442}
2443
2444sub createType($$)
2445{
2446 my ($Attr, $LibVersion) = @_;
2447 my $NewId = ++$MAX_ID;
2448
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002449 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002450 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002451 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002452
2453 return "$NewId";
2454}
2455
2456sub instType($$$)
2457{ # create template instances
2458 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002459
2460 if(not $TypeInfo{$LibVersion}{$Tid}) {
2461 return undef;
2462 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002463 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2464
2465 foreach my $Key (sort keys(%{$Map}))
2466 {
2467 if(my $Val = $Map->{$Key})
2468 {
2469 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2470
2471 if(defined $Attr->{"NameSpace"}) {
2472 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2473 }
2474 foreach (keys(%{$Attr->{"TParam"}})) {
2475 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2476 }
2477 }
2478 else
2479 { # remove absent
2480 # _Traits, etc.
2481 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002482 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002483 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2484 }
2485 foreach (keys(%{$Attr->{"TParam"}}))
2486 {
2487 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2488 delete($Attr->{"TParam"}{$_});
2489 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002490 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002491 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2492 }
2493 }
2494 }
2495 }
2496
2497 my $Tmpl = 0;
2498
2499 if(defined $Attr->{"TParam"})
2500 {
2501 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2502 {
2503 my $PName = $Attr->{"TParam"}{$_}{"name"};
2504
2505 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2506 {
2507 my %Base = get_BaseType($PTid, $LibVersion);
2508
2509 if($Base{"Type"} eq "TemplateParam"
2510 or defined $Base{"Template"})
2511 {
2512 $Tmpl = 1;
2513 last
2514 }
2515 }
2516 }
2517 }
2518
2519 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2520 return "$Id";
2521 }
2522 else
2523 {
2524 if(not $Tmpl) {
2525 delete($Attr->{"Template"});
2526 }
2527
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002528 my $New = createType($Attr, $LibVersion);
2529
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002530 my %EMap = ();
2531 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2532 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2533 }
2534 foreach (keys(%{$Map})) {
2535 $EMap{$_} = $Map->{$_};
2536 }
2537
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002538 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2539 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002540 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002541 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002542 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002543 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002544 {
2545 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2546
2547 if($NBid ne $Bid)
2548 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002549 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2550 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002551 }
2552 }
2553 }
2554
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002555 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002556 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002557 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2558 {
2559 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2560 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2561 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002562 }
2563 }
2564
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002565 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002566 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002567 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2568 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002569 }
2570 }
2571
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002572 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2573 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002574 }
2575
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002576 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002578}
2579
2580sub addMissedTypes_Pre()
2581{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002582 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2584 { # detecting missed typedefs
2585 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2586 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002587 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002588 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002589 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002590 if($TypeType eq "Unknown")
2591 { # template_type_parm
2592 next;
2593 }
2594 my $TypeDeclId = getTypeDeclId($TypeId);
2595 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2596 my $TypedefName = getNameByInfo($MissedTDid);
2597 next if(not $TypedefName);
2598 next if($TypedefName eq "__float80");
2599 next if(isAnon($TypedefName));
2600 if(not $TypeDeclId
2601 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002602 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002603 }
2604 }
2605 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002606 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002607 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002608 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002609 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 next;
2612 }
2613 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002615 if(not $TypedefName) {
2616 next;
2617 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002618 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002619 my %MissedInfo = ( # typedef info
2620 "Name" => $TypedefName,
2621 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002622 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002623 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002624 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 my ($H, $L) = getLocation($MissedTDid);
2626 $MissedInfo{"Header"} = $H;
2627 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002628 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002629 { # other types
2630 next;
2631 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002632 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002633 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002634 next;
2635 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002636 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002638 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002640 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002642 next;
2643 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002644 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002645 next;
2646 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002647 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002648 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002649 next;
2650 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002651 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002653 next;
2654 }
2655 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002656
2657 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002659 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002661 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002662 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002663 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002664
2665 # add missed & remove other
2666 $TypeInfo{$Version} = \%AddTypes;
2667 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668}
2669
2670sub addMissedTypes_Post()
2671{
2672 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2673 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002674 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2675 {
2676 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2677 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2678 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2679 }
2680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002681 }
2682}
2683
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002684sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002685{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002686 my $TypeId = $_[0];
2687 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2688 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002689 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002690 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002692}
2693
2694sub getArraySize($$)
2695{
2696 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002697 if(my $Size = getSize($TypeId))
2698 {
2699 my $Elems = $Size/$BYTE_SIZE;
2700 while($BaseName=~s/\s*\[(\d+)\]//) {
2701 $Elems/=$1;
2702 }
2703 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2704 {
2705 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2706 $Elems/=$BasicSize;
2707 }
2708 }
2709 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002710 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712}
2713
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002714sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002715{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002716 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002717 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002718 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2719 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002720 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002721 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2722 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2723 if(not $NodeType)
2724 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002725 return ();
2726 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002727 if($NodeType eq "tree_vec")
2728 {
2729 if($Pos!=$#Positions)
2730 { # select last vector of parameters ( ns<P1>::type<P2> )
2731 next;
2732 }
2733 }
2734 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2735 foreach my $P (@Params)
2736 {
2737 if($P eq "") {
2738 return ();
2739 }
2740 elsif($P ne "\@skip\@") {
2741 @TmplParams = (@TmplParams, $P);
2742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002743 }
2744 }
2745 return @TmplParams;
2746}
2747
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002748sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002750 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002751 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002752 if(defined $TypeInfo{$Version}{$TypeId}
2753 and $TypeInfo{$Version}{$TypeId}{"Name"})
2754 { # already created
2755 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002756 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002757 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2758 { # incomplete type
2759 return ();
2760 }
2761 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2762
2763 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002764 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002765
2766 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2767 {
2768 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2769 {
2770 if($Info=~/qual[ ]*:/)
2771 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002772 my $NewId = ++$MAX_ID;
2773
2774 $MissedBase{$Version}{$TypeId} = "$NewId";
2775 $MissedBase_R{$Version}{$NewId} = $TypeId;
2776 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2777 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002778 }
2779 }
2780 $TypeAttr{"Type"} = "Typedef";
2781 }
2782 else {
2783 $TypeAttr{"Type"} = getTypeType($TypeId);
2784 }
2785
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002786 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2787 {
2788 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2789 { # local code
2790 return ();
2791 }
2792 }
2793
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002794 if($TypeAttr{"Type"} eq "Unknown") {
2795 return ();
2796 }
2797 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2798 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002799 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002800 if(my $TName = $TypeAttr{"Name"})
2801 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002802 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002803 $TName_Tid{$Version}{$TName} = $TypeId;
2804 return %TypeAttr;
2805 }
2806 else {
2807 return ();
2808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002809 }
2810 elsif($TypeAttr{"Type"} eq "Array")
2811 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002812 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2813 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002814 return ();
2815 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002816 if(my $Algn = getAlgn($TypeId)) {
2817 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2818 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002819 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002822 if(not $BTAttr{"Name"}) {
2823 return ();
2824 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002825 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002826 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002827 if(my $Size = getSize($TypeId)) {
2828 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2829 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002830 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002831 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2832 }
2833 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002834 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002836 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002837 else
2838 {
2839 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002840 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002841 $TypeAttr{"Name"} = $1."[]".$2;
2842 }
2843 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002844 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002846 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002847 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002848 if($BTAttr{"Header"}) {
2849 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002850 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002851 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002852 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2853 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002854 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002855 return ();
2856 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002857 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002858 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002859 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002860 if($TypeAttr{"Name"})
2861 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002862 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002863
2864 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2865 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002866 { # NOTE: register only one int: with built-in decl
2867 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2868 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2869 }
2870 }
2871 return %TypeAttr;
2872 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002873 else {
2874 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002876 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002877 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2878 {
2879 %TypeAttr = getTrivialTypeAttr($TypeId);
2880 if($TypeAttr{"Name"})
2881 {
2882 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2883 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2884 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2885 }
2886 return %TypeAttr;
2887 }
2888 else {
2889 return ();
2890 }
2891 }
2892 elsif($TypeAttr{"Type"} eq "SizeOf")
2893 {
2894 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2895 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2896 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2897 if($TypeAttr{"Name"})
2898 {
2899 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2900 return %TypeAttr;
2901 }
2902 else {
2903 return ();
2904 }
2905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002907 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002908 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2909 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002910 return ();
2911 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002912 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002913 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002914 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002915 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002916 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002917 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002918 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002920 }
2921 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002922 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002923 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002924 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002925 return ();
2926 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002927 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002928 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002929 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002930 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002931 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002932 }
2933 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002934 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002935 {
2936 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002937 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002938 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002939 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002940 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2941 }
2942 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002943 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002944 }
2945 }
2946 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002947 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002948 }
2949 if($TypeAttr{"Type"} eq "Typedef")
2950 {
2951 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002952
2953 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2954 return ();
2955 }
2956
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002957 if(isAnon($TypeAttr{"Name"}))
2958 { # anon typedef to anon type: ._N
2959 return ();
2960 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002961
2962 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2963 { # artificial typedef of "struct X" to "X"
2964 $TypeAttr{"Artificial"} = 1;
2965 }
2966
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002967 if(my $NS = getNameSpace($TypeDeclId))
2968 {
2969 my $TypeName = $TypeAttr{"Name"};
2970 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2971 { # "some_type" is the typedef to "struct some_type" in C++
2972 if($3) {
2973 $TypeAttr{"Name"} = $3."::".$TypeName;
2974 }
2975 }
2976 else
2977 {
2978 $TypeAttr{"NameSpace"} = $NS;
2979 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002980
2981 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2982 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2983 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002984 if($BTAttr{"NameSpace"}
2985 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002986 { # types like "std::fpos<__mbstate_t>" are
2987 # not covered by typedefs in the TU dump
2988 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002989 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2990 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002991 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002992 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002993 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002994 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002996 }
2997 }
2998 }
2999 }
3000 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003001 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003002 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003003 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003004 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3005 { # typedef int*const TYPEDEF; // first
3006 # int foo(TYPEDEF p); // const is optimized out
3007 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3008 if($BTAttr{"Name"}=~/</)
3009 {
3010 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3011 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003013 }
3014 }
3015 }
3016 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3017 }
3018 if(not $TypeAttr{"Size"})
3019 {
3020 if($TypeAttr{"Type"} eq "Pointer") {
3021 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3022 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003023 elsif($BTAttr{"Size"}) {
3024 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003025 }
3026 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003027 if(my $Algn = getAlgn($TypeId)) {
3028 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3029 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003030 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003031 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3032 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003033 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003034 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003035 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003036 { # typedef to "class Class"
3037 # should not be registered in TName_Tid
3038 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3039 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3040 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003041 }
3042 return %TypeAttr;
3043 }
3044}
3045
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003046sub getTreeVec($)
3047{
3048 my %Vector = ();
3049 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3050 {
3051 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3052 { # string length is N-1 because of the null terminator
3053 $Vector{$1} = $2;
3054 }
3055 }
3056 return \%Vector;
3057}
3058
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003059sub get_TemplateParam($$)
3060{
3061 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003062 return () if(not $Type_Id);
3063 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3064 return () if(not $NodeType);
3065 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003066 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003067 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003068 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 my $Num = getNodeIntCst($Type_Id);
3070 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003071 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003072 }
3073 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003074 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003075 }
3076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003077 elsif($NodeType eq "string_cst") {
3078 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003080 elsif($NodeType eq "tree_vec")
3081 {
3082 my $Vector = getTreeVec($Type_Id);
3083 my @Params = ();
3084 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3085 {
3086 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3087 push(@Params, $P2);
3088 }
3089 }
3090 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003091 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003092 elsif($NodeType eq "parm_decl")
3093 {
3094 (getNameByInfo($Type_Id));
3095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003096 else
3097 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003098 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003099 my $PName = $ParamAttr{"Name"};
3100 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003101 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003103 if($PName=~/\>/)
3104 {
3105 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003106 $PName = $Cover;
3107 }
3108 }
3109 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003110 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3112 # template<typename _Key, typename _Compare = std::less<_Key>
3113 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3114 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3115 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3116 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003117 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003119 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003120 }
3121}
3122
3123sub cover_stdcxx_typedef($)
3124{
3125 my $TypeName = $_[0];
3126 if(my @Covers = sort {length($a)<=>length($b)}
3127 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3128 { # take the shortest typedef
3129 # FIXME: there may be more than
3130 # one typedefs to the same type
3131 return $Covers[0];
3132 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003133 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003134 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3135 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3136 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003137 if(my $Cover = $Covers[0])
3138 {
3139 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3140 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003142 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003143 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003144}
3145
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003146sub getNodeIntCst($)
3147{
3148 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003149 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003150 if($EnumMembName_Id{$Version}{$CstId}) {
3151 return $EnumMembName_Id{$Version}{$CstId};
3152 }
3153 elsif((my $Value = getTreeValue($CstId)) ne "")
3154 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003155 if($Value eq "0")
3156 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003157 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158 return "false";
3159 }
3160 else {
3161 return "0";
3162 }
3163 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003164 elsif($Value eq "1")
3165 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003166 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167 return "true";
3168 }
3169 else {
3170 return "1";
3171 }
3172 }
3173 else {
3174 return $Value;
3175 }
3176 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003177 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003178}
3179
3180sub getNodeStrCst($)
3181{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003182 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3183 {
3184 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003185 {
3186 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3187 { # string length is N-1 because of the null terminator
3188 return substr($1, 0, $2-1);
3189 }
3190 else
3191 { # identifier_node
3192 return substr($1, 0, $2);
3193 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003195 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003196 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003197}
3198
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003199sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003200{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003202 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3203 if($Type eq "FieldPtr") {
3204 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3205 }
3206 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3207 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003208 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 if($Type eq "MethodPtr")
3210 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003211 if(my $Size = getSize($TypeId))
3212 {
3213 $Size/=$BYTE_SIZE;
3214 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003216 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003217 if(my $Algn = getAlgn($TypeId)) {
3218 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003220 # Return
3221 if($Type eq "FieldPtr")
3222 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003223 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003224 if($ReturnAttr{"Name"}) {
3225 $MemPtrName .= $ReturnAttr{"Name"};
3226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003227 $TypeAttr{"Return"} = $PtrId;
3228 }
3229 else
3230 {
3231 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3232 {
3233 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003234 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3235 if(not $ReturnAttr{"Name"})
3236 { # templates
3237 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003239 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003240 $TypeAttr{"Return"} = $ReturnTypeId;
3241 }
3242 }
3243 # Class
3244 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3245 {
3246 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003247 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003248 if($Class{"Name"}) {
3249 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3250 }
3251 else {
3252 $MemPtrName .= " (*)";
3253 }
3254 }
3255 else {
3256 $MemPtrName .= " (*)";
3257 }
3258 # Parameters
3259 if($Type eq "FuncPtr"
3260 or $Type eq "MethodPtr")
3261 {
3262 my @ParamTypeName = ();
3263 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3264 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003265 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003266 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003267 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003268 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003269 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3270 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003272 my $PTypeId = $1;
3273 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003274 if(not $ParamAttr{"Name"})
3275 { # templates (template_type_parm), etc.
3276 return ();
3277 }
3278 if($ParamAttr{"Name"} eq "void") {
3279 last;
3280 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003281 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003282 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003283 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003284 push(@ParamTypeName, $ParamAttr{"Name"});
3285 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003286 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3287 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003288 }
3289 else {
3290 last;
3291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003292 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003293 else {
3294 last;
3295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003296 }
3297 }
3298 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3299 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003300 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003301 return %TypeAttr;
3302}
3303
3304sub getTreeTypeName($)
3305{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003306 my $TypeId = $_[0];
3307 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003309 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003310 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003311 if(my $Name = getNameByInfo($TypeId))
3312 { # bit_size_type
3313 return $Name;
3314 }
3315 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003316 return "unsigned int";
3317 }
3318 else {
3319 return "int";
3320 }
3321 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003322 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003323 return getNameByInfo($1);
3324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003325 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003326 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003327}
3328
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003329sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003330{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003331 my $Ptd = pointTo($_[0]);
3332 return 0 if(not $Ptd);
3333 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003334 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003335 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3336 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003337 }
3338 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003339 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3340 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003341 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003342 if($InfoT1 eq "pointer_type"
3343 and $InfoT2 eq "function_type") {
3344 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003345 }
3346 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003347 return 0;
3348}
3349
3350sub isMethodPtr($)
3351{
3352 my $Ptd = pointTo($_[0]);
3353 return 0 if(not $Ptd);
3354 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3355 {
3356 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3357 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3358 and $Info=~/ ptrmem /) {
3359 return 1;
3360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003361 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003362 return 0;
3363}
3364
3365sub isFieldPtr($)
3366{
3367 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3368 {
3369 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3370 and $Info=~/ ptrmem /) {
3371 return 1;
3372 }
3373 }
3374 return 0;
3375}
3376
3377sub pointTo($)
3378{
3379 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3380 {
3381 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3382 return $1;
3383 }
3384 }
3385 return "";
3386}
3387
3388sub getTypeTypeByTypeId($)
3389{
3390 my $TypeId = $_[0];
3391 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3392 {
3393 my $NType = $NodeType{$TType};
3394 if($NType eq "Intrinsic") {
3395 return $NType;
3396 }
3397 elsif(isFuncPtr($TypeId)) {
3398 return "FuncPtr";
3399 }
3400 elsif(isMethodPtr($TypeId)) {
3401 return "MethodPtr";
3402 }
3403 elsif(isFieldPtr($TypeId)) {
3404 return "FieldPtr";
3405 }
3406 elsif($NType ne "Other") {
3407 return $NType;
3408 }
3409 }
3410 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003411}
3412
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003413my %UnQual = (
3414 "r"=>"restrict",
3415 "v"=>"volatile",
3416 "c"=>"const",
3417 "cv"=>"const volatile"
3418);
3419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003420sub getQual($)
3421{
3422 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003423 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3424 {
3425 my ($Qual, $To) = ();
3426 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3427 $Qual = $UnQual{$1};
3428 }
3429 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3430 $To = $1;
3431 }
3432 if($Qual and $To) {
3433 return ($Qual, $To);
3434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003435 }
3436 return ();
3437}
3438
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439sub getQualType($)
3440{
3441 if($_[0] eq "const volatile") {
3442 return "ConstVolatile";
3443 }
3444 return ucfirst($_[0]);
3445}
3446
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003447sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003448{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003449 my $TypeId = $_[0];
3450 my $TypeDeclId = getTypeDeclId($TypeId);
3451 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003452 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003453 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3454 return "Typedef";
3455 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003456 }
3457 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3458 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003459 if(($Qual or $To) and $TypeDeclId
3460 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003461 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003462 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003463 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003464 elsif(not $MissedBase_R{$Version}{$TypeId}
3465 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003466 return "Typedef";
3467 }
3468 elsif($Qual)
3469 { # qualified types
3470 return getQualType($Qual);
3471 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003472
3473 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3474 { # typedef struct { ... } name
3475 $TypeTypedef{$Version}{$TypeId} = $1;
3476 }
3477
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003478 my $TypeType = getTypeTypeByTypeId($TypeId);
3479 if($TypeType eq "Struct")
3480 {
3481 if($TypeDeclId
3482 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3483 return "Template";
3484 }
3485 }
3486 return $TypeType;
3487}
3488
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003489sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003490{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003491 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003492 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003493 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3494 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3495 return 0;
3496 }
3497 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3498 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003499 if(my $TDid = getTypeDeclId($_[0]))
3500 {
3501 if(getTypeId($TDid) eq $_[0]
3502 and getNameByInfo($TDid))
3503 {
3504 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3505 return $1;
3506 }
3507 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003508 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 }
3510 }
3511 return 0;
3512}
3513
3514sub selectBaseType($)
3515{
3516 my $TypeId = $_[0];
3517 if(defined $MissedTypedef{$Version}{$TypeId})
3518 { # add missed typedefs
3519 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3520 return ($TypeId, "");
3521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3524 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003525
3526 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3527 my $MB = $MissedBase{$Version}{$TypeId};
3528
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003529 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003530 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003531 and (getTypeId($1) ne $TypeId)
3532 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003533 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003534 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003536 elsif($MB)
3537 { # add base
3538 return ($MB, "");
3539 }
3540 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003542 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003543 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003544 elsif($Qual or $To)
3545 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003546 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003547 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003548 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003550 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003551 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003553 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003554 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003555 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003556 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003557 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003559 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003560 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003561 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003562 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003563 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003565 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003566
3567 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003568}
3569
3570sub getSymbolInfo_All()
3571{
3572 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3573 { # reverse order
3574 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003575 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003576 }
3577 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003578
3579 if($ADD_TMPL_INSTANCES)
3580 {
3581 # templates
3582 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3583 {
3584 my %Map = ();
3585
3586 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3587 {
3588 if(defined $TemplateMap{$Version}{$ClassId})
3589 {
3590 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3591 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3592 }
3593 }
3594 }
3595
3596 if(defined $TemplateMap{$Version}{$Sid})
3597 {
3598 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3599 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3600 }
3601 }
3602
3603 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3604 {
3605 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3606 {
3607 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3608 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3609 }
3610 }
3611 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3612 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3613 }
3614 }
3615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003616}
3617
3618sub getVarInfo_All()
3619{
3620 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3621 { # reverse order
3622 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003623 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003624 }
3625 }
3626}
3627
3628sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003629 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003630}
3631
3632sub getVarInfo($)
3633{
3634 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003635 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003636 {
3637 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3638 if($NSInfoType and $NSInfoType eq "function_decl") {
3639 return;
3640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003641 }
3642 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3643 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3644 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3645 delete($SymbolInfo{$Version}{$InfoId});
3646 return;
3647 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003648 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003649 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003650 delete($SymbolInfo{$Version}{$InfoId});
3651 return;
3652 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003653 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3654 delete($SymbolInfo{$Version}{$InfoId});
3655 return;
3656 }
3657 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003658 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3659 {
3660 if($OSgroup eq "windows")
3661 { # cut the offset
3662 $MnglName=~s/\@\d+\Z//g;
3663 }
3664 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003666 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003667 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003668 { # validate mangled name
3669 delete($SymbolInfo{$Version}{$InfoId});
3670 return;
3671 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003672 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003673 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003674 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003675 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003676 }
3677 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3678 { # non-public global data
3679 delete($SymbolInfo{$Version}{$InfoId});
3680 return;
3681 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003683 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003684 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003685 if(not defined $TypeInfo{$Version}{$Rid}
3686 or not $TypeInfo{$Version}{$Rid}{"Name"})
3687 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003688 delete($SymbolInfo{$Version}{$InfoId});
3689 return;
3690 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003691 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3692 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003693 if(defined $Val) {
3694 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003696 }
3697 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003698 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3699 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003700 if(not defined $TypeInfo{$Version}{$ClassId}
3701 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3702 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003703 delete($SymbolInfo{$Version}{$InfoId});
3704 return;
3705 }
3706 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003707 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3708 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003710 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003711 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003712 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003713 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003714 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003715 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003716 if(not $CheckHeadersOnly)
3717 {
3718 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3719 {
3720 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3721 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3722 {
3723 if(link_symbol($ShortName, $Version, "-Deps"))
3724 { # "const" global data is mangled as _ZL... in the TU dump
3725 # but not mangled when compiling a C shared library
3726 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3727 }
3728 }
3729 }
3730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003731 if($COMMON_LANGUAGE{$Version} eq "C++")
3732 {
3733 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3734 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003735 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003736 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3737 }
3738 }
3739 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3740 { # try to mangle symbol (link with libraries)
3741 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3742 }
3743 if($OStarget eq "windows")
3744 {
3745 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3746 { # link MS C++ symbols from library with GCC symbols from headers
3747 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3748 }
3749 }
3750 }
3751 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3752 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3753 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003754 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3755 {
3756 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3757 { # non-target symbols
3758 delete($SymbolInfo{$Version}{$InfoId});
3759 return;
3760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003761 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003762 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3763 {
3764 if(defined $MissedTypedef{$Version}{$Rid})
3765 {
3766 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3767 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3768 }
3769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003770 }
3771 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003772 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003773 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3774 }
3775 if($ShortName=~/\A(_Z|\?)/) {
3776 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3777 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003778
3779 if($ExtraDump) {
3780 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003782}
3783
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003784sub isConstType($$)
3785{
3786 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003787 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003788 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003789 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003790 }
3791 return ($Base{"Type"} eq "Const");
3792}
3793
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003794sub getTrivialName($$)
3795{
3796 my ($TypeInfoId, $TypeId) = @_;
3797 my %TypeAttr = ();
3798 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3799 if(not $TypeAttr{"Name"}) {
3800 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3801 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003802 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003803 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003804 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003805 if(isAnon($TypeAttr{"Name"}))
3806 {
3807 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003808 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003809 { # searching for a first not anon scope
3810 if($NSId eq $NameSpaceId) {
3811 last;
3812 }
3813 else
3814 {
3815 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3816 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003817 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003818 last;
3819 }
3820 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003821 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003822 }
3823 }
3824 else
3825 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003826 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003827 {
3828 if($NameSpaceId ne $TypeId) {
3829 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 }
3832 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003833 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003834 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3835 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003836 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003838 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003839 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003840 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003841 if($TypeAttr{"NameSpace"}) {
3842 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003844 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003845 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3846 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003847 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003848 if(my @TParams = getTParams($TypeId, "Type")) {
3849 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3850 }
3851 else {
3852 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003854 }
3855 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3856}
3857
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003858sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003859{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003860 my $TypeId = $_[0];
3861 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003862
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003863 my %TypeAttr = ();
3864
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003865 if($TemplateDecl{$Version}{$TypeId})
3866 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003867 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003868 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003869
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003870 setTypeAccess($TypeId, \%TypeAttr);
3871 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3872 if(isBuiltIn($TypeAttr{"Header"}))
3873 {
3874 delete($TypeAttr{"Header"});
3875 delete($TypeAttr{"Line"});
3876 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003877
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003878 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003879 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3880 if(not $TypeAttr{"Name"}) {
3881 return ();
3882 }
3883 if(not $TypeAttr{"NameSpace"}) {
3884 delete($TypeAttr{"NameSpace"});
3885 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003886
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003887 if($TypeAttr{"Type"} eq "Intrinsic")
3888 {
3889 if(defined $TypeAttr{"Header"})
3890 {
3891 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3892 { # support for SUSE 11.2
3893 # integer_type has srcp dump{1-2}.i
3894 delete($TypeAttr{"Header"});
3895 }
3896 }
3897 }
3898
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003899 my $Tmpl = undef;
3900
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003901 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003902 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003903 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3904
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003905 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003906 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003907 foreach my $Pos (0 .. $#TParams)
3908 {
3909 my $Val = $TParams[$Pos];
3910 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3911
3912 if(not defined $TypeAttr{"Template"})
3913 {
3914 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3915
3916 if($Base{"Type"} eq "TemplateParam"
3917 or defined $Base{"Template"}) {
3918 $TypeAttr{"Template"} = 1;
3919 }
3920 }
3921
3922 if($Tmpl)
3923 {
3924 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3925 {
3926 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3927
3928 if($Val eq $Arg) {
3929 $TypeAttr{"Template"} = 1;
3930 }
3931 }
3932 }
3933 }
3934
3935 if($Tmpl)
3936 {
3937 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3938 {
3939 if($Pos>$#TParams)
3940 {
3941 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3942 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3943 }
3944 }
3945 }
3946 }
3947
3948 if($ADD_TMPL_INSTANCES)
3949 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003950 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003951 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003952 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003953 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003954 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003955 {
3956 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3957 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3958 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003959 }
3960 if(not getTreeAttr_Binf($TypeId))
3961 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003962 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3963 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3964 }
3965 }
3966 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003967 }
3968 }
3969 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003970
3971 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3972
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003973 if(my $Size = getSize($TypeId))
3974 {
3975 $Size = $Size/$BYTE_SIZE;
3976 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003977 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003978 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003979 {
3980 if($ExtraDump)
3981 {
3982 if(not defined $TypeAttr{"Memb"}
3983 and not $Tmpl)
3984 { # declaration only
3985 $TypeAttr{"Forward"} = 1;
3986 }
3987 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003988 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003989
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003990 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003991 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003992 {
3993 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003994 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003995 }
3996 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003997 or $TypeAttr{"Type"} eq "Class")
3998 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003999 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004000 if($Skip) {
4001 return ();
4002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004003 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004004 if(my $Algn = getAlgn($TypeId)) {
4005 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004007 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004008
4009 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4010 {
4011 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004012 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004013 {
4014 if(not isAnon($TypeAttr{"Name"})) {
4015 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4016 }
4017 }
4018 }
4019
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004020 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004021 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4022 {
4023 my @Entries = split(/\n/, $VTable);
4024 foreach (1 .. $#Entries)
4025 {
4026 my $Entry = $Entries[$_];
4027 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004028 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004029 }
4030 }
4031 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004032
4033 if($TypeAttr{"Type"} eq "Enum")
4034 {
4035 if(not $TypeAttr{"NameSpace"})
4036 {
4037 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4038 {
4039 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004040 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004041 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004042 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004043 "Header"=>$TypeAttr{"Header"}
4044 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004045 if(isAnon($TypeAttr{"Name"}))
4046 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004047 if($ExtraDump
4048 or is_target_header($TypeAttr{"Header"}, $Version))
4049 {
4050 %{$Constants{$Version}{$MName}} = (
4051 "Value" => $MVal,
4052 "Header" => $TypeAttr{"Header"}
4053 );
4054 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004055 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004056 }
4057 }
4058 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004059 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004060 {
4061 if(defined $TypedefToAnon{$TypeId}) {
4062 $TypeAttr{"AnonTypedef"} = 1;
4063 }
4064 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004066 return %TypeAttr;
4067}
4068
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004069sub simplifyVTable($)
4070{
4071 my $Content = $_[0];
4072 if($Content=~s/ \[with (.+)]//)
4073 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4074 if(my @Elems = separate_Params($1, 0, 0))
4075 {
4076 foreach my $Elem (@Elems)
4077 {
4078 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4079 {
4080 my ($Arg, $Val) = ($1, $2);
4081
4082 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4083 $Content=~s/,\s*$Arg\b//g;
4084 }
4085 else {
4086 $Content=~s/\b$Arg\b/$Val/g;
4087 }
4088 }
4089 }
4090 }
4091 }
4092
4093 return $Content;
4094}
4095
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004096sub detect_lang($)
4097{
4098 my $TypeId = $_[0];
4099 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004100 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004101 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004102 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4103 }
4104 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004105 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004106 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004107 while($Fncs)
4108 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004109 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004110 return 1;
4111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004112 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004113 }
4114 }
4115 return 0;
4116}
4117
4118sub setSpec($$)
4119{
4120 my ($TypeId, $TypeAttr) = @_;
4121 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4122 if($Info=~/\s+spec\s+/) {
4123 $TypeAttr->{"Spec"} = 1;
4124 }
4125}
4126
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004127sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004128{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004129 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004131 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004132 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004133 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 my $Pos = 0;
4135 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4136 {
4137 my ($Access, $BInfoId) = ($1, $2);
4138 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004139
4140 if($ClassId==$TypeId)
4141 { # class A<N>:public A<N-1>
4142 next;
4143 }
4144
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004145 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4146 if(not $CType or $CType eq "template_type_parm"
4147 or $CType eq "typename_type")
4148 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004149 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004151 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004152 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004153 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4154 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004155 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004156 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4157 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004158 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004160 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004161 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4162 }
4163 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004164 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004165 }
4166 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004167 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004168}
4169
4170sub getBinfClassId($)
4171{
4172 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4173 $Info=~/type[ ]*:[ ]*@(\d+) /;
4174 return $1;
4175}
4176
4177sub unmangledFormat($$)
4178{
4179 my ($Name, $LibVersion) = @_;
4180 $Name = uncover_typedefs($Name, $LibVersion);
4181 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4182 $Name=~s/\(\w+\)(\d)/$1/;
4183 return $Name;
4184}
4185
4186sub modelUnmangled($$)
4187{
4188 my ($InfoId, $Compiler) = @_;
4189 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4190 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4191 }
4192 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4193 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4194 $PureSignature = "~".$PureSignature;
4195 }
4196 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4197 {
4198 my (@Params, @ParamTypes) = ();
4199 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4200 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4201 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4202 }
4203 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4204 { # checking parameters
4205 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004206 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004207 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004208 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004209
4210 if($PName eq "this"
4211 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4212 {
4213 next;
4214 }
4215
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004216 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004217 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004218 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004219 }
4220 @ParamTypes = (@ParamTypes, $PTName);
4221 }
4222 if(@ParamTypes) {
4223 $PureSignature .= "(".join(", ", @ParamTypes).")";
4224 }
4225 else
4226 {
4227 if($Compiler eq "MSVC")
4228 {
4229 $PureSignature .= "(void)";
4230 }
4231 else
4232 { # GCC
4233 $PureSignature .= "()";
4234 }
4235 }
4236 $PureSignature = delete_keywords($PureSignature);
4237 }
4238 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4239 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004240 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004241 $PureSignature = $ClassName."::".$PureSignature;
4242 }
4243 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4244 $PureSignature = $NS."::".$PureSignature;
4245 }
4246 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4247 $PureSignature .= " const";
4248 }
4249 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4250 $PureSignature .= " volatile";
4251 }
4252 my $ShowReturn = 0;
4253 if($Compiler eq "MSVC"
4254 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4255 {
4256 $ShowReturn=1;
4257 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004258 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4259 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004260 {
4261 $ShowReturn=1;
4262 }
4263 if($ShowReturn)
4264 { # mangled names for template function specializations include return value
4265 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4266 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004267 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004268 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4269 $PureSignature = $ReturnName." ".$PureSignature;
4270 }
4271 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004272 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004273}
4274
4275sub mangle_symbol($$$)
4276{ # mangling for simple methods
4277 # see gcc-4.6.0/gcc/cp/mangle.c
4278 my ($InfoId, $LibVersion, $Compiler) = @_;
4279 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4280 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4281 }
4282 my $Mangled = "";
4283 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004284 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004285 }
4286 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004287 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004288 }
4289 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4290}
4291
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004292sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004293{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004294 my ($InfoId, $LibVersion) = @_;
4295 return "";
4296}
4297
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004298sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004299{ # see gcc-4.6.0/gcc/cp/mangle.c
4300 my ($InfoId, $LibVersion) = @_;
4301 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004302 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004303 my %Repl = ();# SN_ replacements
4304 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4305 {
4306 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4307 if($MangledClass!~/\AN/) {
4308 $MangledClass = "N".$MangledClass;
4309 }
4310 else {
4311 $MangledClass=~s/E\Z//;
4312 }
4313 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4314 $MangledClass=~s/\AN/NV/;
4315 }
4316 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4317 $MangledClass=~s/\AN/NK/;
4318 }
4319 $Mangled .= $MangledClass;
4320 }
4321 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4322 { # mangled by name due to the absence of structured info
4323 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4324 if($MangledNS!~/\AN/) {
4325 $MangledNS = "N".$MangledNS;
4326 }
4327 else {
4328 $MangledNS=~s/E\Z//;
4329 }
4330 $Mangled .= $MangledNS;
4331 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004332 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004333 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004334 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004335 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004336 foreach (@TPos) {
4337 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4338 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004339 }
4340 elsif($TmplParams)
4341 { # remangling mode
4342 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004343 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004344 }
4345 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4346 $Mangled .= "C1";
4347 }
4348 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4349 $Mangled .= "D0";
4350 }
4351 elsif($ShortName)
4352 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004353 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4354 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004355 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004356 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004357 { # "const" global data is mangled as _ZL...
4358 $Mangled .= "L";
4359 }
4360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004361 if($ShortName=~/\Aoperator(\W.*)\Z/)
4362 {
4363 my $Op = $1;
4364 $Op=~s/\A[ ]+//g;
4365 if(my $OpMngl = $OperatorMangling{$Op}) {
4366 $Mangled .= $OpMngl;
4367 }
4368 else { # conversion operator
4369 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4370 }
4371 }
4372 else {
4373 $Mangled .= length($ShortName).$ShortName;
4374 }
4375 if(@TParams)
4376 { # templates
4377 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004378 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004379 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4380 }
4381 $Mangled .= "E";
4382 }
4383 if(not $ClassId and @TParams) {
4384 add_substitution($ShortName, \%Repl, 0);
4385 }
4386 }
4387 if($ClassId or $NameSpace) {
4388 $Mangled .= "E";
4389 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004390 if(@TParams)
4391 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004392 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004393 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4394 }
4395 }
4396 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4397 {
4398 my @Params = ();
4399 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4400 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4401 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4402 }
4403 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4404 { # checking parameters
4405 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4406 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4407 }
4408 if(not @Params) {
4409 $Mangled .= "v";
4410 }
4411 }
4412 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4413 $Mangled = write_stdcxx_substitution($Mangled);
4414 if($Mangled eq "_Z") {
4415 return "";
4416 }
4417 return $Mangled;
4418}
4419
4420sub correct_incharge($$$)
4421{
4422 my ($InfoId, $LibVersion, $Mangled) = @_;
4423 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4424 {
4425 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004426 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004427 }
4428 }
4429 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4430 {
4431 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004432 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433 }
4434 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004435 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004436 }
4437 }
4438 return $Mangled;
4439}
4440
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004441sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004442{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004443 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004444 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004445 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004446 return $Name;
4447 }
4448 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004449 while(my $CPos = find_center($TParams, "<"))
4450 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004451 $TParams = substr($TParams, $CPos);
4452 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004453 if($TParams=~s/\A<(.+)>\Z/$1/) {
4454 $Name=~s/<\Q$TParams\E>\Z//;
4455 }
4456 else
4457 { # error
4458 $TParams = "";
4459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004460 return ($Name, $TParams);
4461}
4462
4463sub get_sub_ns($)
4464{
4465 my $Name = $_[0];
4466 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004467 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004468 {
4469 push(@NS, substr($Name, 0, $CPos));
4470 $Name = substr($Name, $CPos);
4471 $Name=~s/\A:://;
4472 }
4473 return (join("::", @NS), $Name);
4474}
4475
4476sub mangle_ns($$$)
4477{
4478 my ($Name, $LibVersion, $Repl) = @_;
4479 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4480 {
4481 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4482 $Mangled=~s/\AN(.+)E\Z/$1/;
4483 return $Mangled;
4484
4485 }
4486 else
4487 {
4488 my ($MangledNS, $SubNS) = ("", "");
4489 ($SubNS, $Name) = get_sub_ns($Name);
4490 if($SubNS) {
4491 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4492 }
4493 $MangledNS .= length($Name).$Name;
4494 add_substitution($MangledNS, $Repl, 0);
4495 return $MangledNS;
4496 }
4497}
4498
4499sub mangle_param($$$)
4500{
4501 my ($PTid, $LibVersion, $Repl) = @_;
4502 my ($MPrefix, $Mangled) = ("", "");
4503 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004504 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004505 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004506 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004507 if(not $BaseType_Name) {
4508 return "";
4509 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004510 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004511 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004512 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4513 while($Suffix=~/(&|\*|const)\Z/)
4514 {
4515 if($Suffix=~s/[ ]*&\Z//) {
4516 $MPrefix .= "R";
4517 }
4518 if($Suffix=~s/[ ]*\*\Z//) {
4519 $MPrefix .= "P";
4520 }
4521 if($Suffix=~s/[ ]*const\Z//)
4522 {
4523 if($MPrefix=~/R|P/
4524 or $Suffix=~/&|\*/) {
4525 $MPrefix .= "K";
4526 }
4527 }
4528 if($Suffix=~s/[ ]*volatile\Z//) {
4529 $MPrefix .= "V";
4530 }
4531 #if($Suffix=~s/[ ]*restrict\Z//) {
4532 #$MPrefix .= "r";
4533 #}
4534 }
4535 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4536 $Mangled .= $Token;
4537 }
4538 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4539 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004540 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004541 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004542 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004543 foreach (@TPos) {
4544 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4545 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004546 }
4547 elsif($TmplParams)
4548 { # remangling mode
4549 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004550 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004551 }
4552 my $MangledNS = "";
4553 my ($SubNS, $SName) = get_sub_ns($ShortName);
4554 if($SubNS) {
4555 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4556 }
4557 $MangledNS .= length($SName).$SName;
4558 if(@TParams) {
4559 add_substitution($MangledNS, $Repl, 0);
4560 }
4561 $Mangled .= "N".$MangledNS;
4562 if(@TParams)
4563 { # templates
4564 $Mangled .= "I";
4565 foreach my $TParam (@TParams) {
4566 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4567 }
4568 $Mangled .= "E";
4569 }
4570 $Mangled .= "E";
4571 }
4572 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4573 {
4574 if($BaseType{"Type"} eq "MethodPtr") {
4575 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4576 }
4577 else {
4578 $Mangled .= "PF";
4579 }
4580 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4581 my @Params = keys(%{$BaseType{"Param"}});
4582 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4583 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4584 }
4585 if(not @Params) {
4586 $Mangled .= "v";
4587 }
4588 $Mangled .= "E";
4589 }
4590 elsif($BaseType{"Type"} eq "FieldPtr")
4591 {
4592 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4593 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4594 }
4595 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4596 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4597 {
4598 if($Mangled eq $Optimized)
4599 {
4600 if($ShortName!~/::/)
4601 { # remove "N ... E"
4602 if($MPrefix) {
4603 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4604 }
4605 else {
4606 $Mangled=~s/\AN(.+)E\Z/$1/g;
4607 }
4608 }
4609 }
4610 else {
4611 $Mangled = $Optimized;
4612 }
4613 }
4614 add_substitution($Mangled, $Repl, 1);
4615 return $Mangled;
4616}
4617
4618sub mangle_template_param($$$)
4619{ # types + literals
4620 my ($TParam, $LibVersion, $Repl) = @_;
4621 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4622 return mangle_param($TPTid, $LibVersion, $Repl);
4623 }
4624 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4625 { # class_name<1u>::method(...)
4626 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4627 }
4628 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4629 { # class_name<(signed char)1>::method(...)
4630 return "L".$IntrinsicMangling{$1}.$2."E";
4631 }
4632 elsif($TParam eq "true")
4633 { # class_name<true>::method(...)
4634 return "Lb1E";
4635 }
4636 elsif($TParam eq "false")
4637 { # class_name<true>::method(...)
4638 return "Lb0E";
4639 }
4640 else { # internal error
4641 return length($TParam).$TParam;
4642 }
4643}
4644
4645sub add_substitution($$$)
4646{
4647 my ($Value, $Repl, $Rec) = @_;
4648 if($Rec)
4649 { # subtypes
4650 my @Subs = ($Value);
4651 while($Value=~s/\A(R|P|K)//) {
4652 push(@Subs, $Value);
4653 }
4654 foreach (reverse(@Subs)) {
4655 add_substitution($_, $Repl, 0);
4656 }
4657 return;
4658 }
4659 return if($Value=~/\AS(\d*)_\Z/);
4660 $Value=~s/\AN(.+)E\Z/$1/g;
4661 return if(defined $Repl->{$Value});
4662 return if(length($Value)<=1);
4663 return if($StdcxxMangling{$Value});
4664 # check for duplicates
4665 my $Base = $Value;
4666 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4667 {
4668 my $Num = $Repl->{$Type};
4669 my $Replace = macro_mangle($Num);
4670 $Base=~s/\Q$Replace\E/$Type/;
4671 }
4672 if(my $OldNum = $Repl->{$Base})
4673 {
4674 $Repl->{$Value} = $OldNum;
4675 return;
4676 }
4677 my @Repls = sort {$b<=>$a} values(%{$Repl});
4678 if(@Repls) {
4679 $Repl->{$Value} = $Repls[0]+1;
4680 }
4681 else {
4682 $Repl->{$Value} = -1;
4683 }
4684 # register duplicates
4685 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004686 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004687 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4688 {
4689 next if($Base eq $Type);
4690 my $Num = $Repl->{$Type};
4691 my $Replace = macro_mangle($Num);
4692 $Base=~s/\Q$Type\E/$Replace/;
4693 $Repl->{$Base} = $Repl->{$Value};
4694 }
4695}
4696
4697sub macro_mangle($)
4698{
4699 my $Num = $_[0];
4700 if($Num==-1) {
4701 return "S_";
4702 }
4703 else
4704 {
4705 my $Code = "";
4706 if($Num<10)
4707 { # S0_, S1_, S2_, ...
4708 $Code = $Num;
4709 }
4710 elsif($Num>=10 and $Num<=35)
4711 { # SA_, SB_, SC_, ...
4712 $Code = chr(55+$Num);
4713 }
4714 else
4715 { # S10_, S11_, S12_
4716 $Code = $Num-26; # 26 is length of english alphabet
4717 }
4718 return "S".$Code."_";
4719 }
4720}
4721
4722sub write_stdcxx_substitution($)
4723{
4724 my $Mangled = $_[0];
4725 if($StdcxxMangling{$Mangled}) {
4726 return $StdcxxMangling{$Mangled};
4727 }
4728 else
4729 {
4730 my @Repls = keys(%StdcxxMangling);
4731 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4732 foreach my $MangledType (@Repls)
4733 {
4734 my $Replace = $StdcxxMangling{$MangledType};
4735 #if($Mangled!~/$Replace/) {
4736 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4737 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4738 #}
4739 }
4740 }
4741 return $Mangled;
4742}
4743
4744sub write_substitution($$)
4745{
4746 my ($Mangled, $Repl) = @_;
4747 if(defined $Repl->{$Mangled}
4748 and my $MnglNum = $Repl->{$Mangled}) {
4749 $Mangled = macro_mangle($MnglNum);
4750 }
4751 else
4752 {
4753 my @Repls = keys(%{$Repl});
4754 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4755 # FIXME: how to apply replacements? by num or by pos
4756 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4757 foreach my $MangledType (@Repls)
4758 {
4759 my $Replace = macro_mangle($Repl->{$MangledType});
4760 if($Mangled!~/$Replace/) {
4761 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4762 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4763 }
4764 }
4765 }
4766 return $Mangled;
4767}
4768
4769sub delete_keywords($)
4770{
4771 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004772 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004773 return $TypeName;
4774}
4775
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004776sub uncover_typedefs($$)
4777{
4778 my ($TypeName, $LibVersion) = @_;
4779 return "" if(not $TypeName);
4780 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4781 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4782 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004783 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004784 while($TypeName_New ne $TypeName_Pre)
4785 {
4786 $TypeName_Pre = $TypeName_New;
4787 my $TypeName_Copy = $TypeName_New;
4788 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004789 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004790 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004791 if(not $Intrinsic_Keywords{$1}) {
4792 $Words{$1} = 1;
4793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004794 }
4795 foreach my $Word (keys(%Words))
4796 {
4797 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4798 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004799 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004800 if($BaseType_Name=~/\([\*]+\)/)
4801 { # FuncPtr
4802 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4803 {
4804 my $Type_Suffix = $1;
4805 $TypeName_New = $BaseType_Name;
4806 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004807 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004808 }
4809 }
4810 }
4811 else
4812 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004813 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004814 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004815 }
4816 }
4817 }
4818 }
4819 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4820}
4821
4822sub isInternal($)
4823{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004824 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4825 {
4826 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4827 {
4828 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4829 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4830 return 1;
4831 }
4832 }
4833 }
4834 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004835}
4836
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004837sub getDataVal($$)
4838{
4839 my ($InfoId, $TypeId) = @_;
4840 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4841 {
4842 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4843 {
4844 if(defined $LibInfo{$Version}{"info_type"}{$1}
4845 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004846 {
4847 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004848 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004849 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4850 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004851 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004852 if(my $Addr = getTreeAttr_Op($1)) {
4853 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004854 }
4855 }
4856 }
4857 }
4858 else {
4859 return getInitVal($1, $TypeId);
4860 }
4861 }
4862 }
4863 return undef;
4864}
4865
4866sub getInitVal($$)
4867{
4868 my ($InfoId, $TypeId) = @_;
4869 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4870 {
4871 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4872 {
4873 if($InfoType eq "integer_cst")
4874 {
4875 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004876 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004877 { # characters
4878 $Val = chr($Val);
4879 }
4880 return $Val;
4881 }
4882 elsif($InfoType eq "string_cst") {
4883 return getNodeStrCst($InfoId);
4884 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004885 elsif($InfoType eq "var_decl")
4886 {
4887 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4888 return $Name;
4889 }
4890 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004891 }
4892 }
4893 return undef;
4894}
4895
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004896sub set_Class_And_Namespace($)
4897{
4898 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004899 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004900 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004901 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004902 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004903 my $NSInfoId = $1;
4904 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4905 {
4906 if($InfoType eq "namespace_decl") {
4907 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4908 }
4909 elsif($InfoType eq "record_type") {
4910 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4911 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004913 }
4914 }
4915 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4916 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004917 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004918 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004919 { # skip
4920 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004922 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004923
4924 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004925}
4926
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004927sub debugMangling($)
4928{
4929 my $LibVersion = $_[0];
4930 my %Mangled = ();
4931 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4932 {
4933 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4934 {
4935 if($Mngl=~/\A(_Z|\?)/) {
4936 $Mangled{$Mngl}=$InfoId;
4937 }
4938 }
4939 }
4940 translateSymbols(keys(%Mangled), $LibVersion);
4941 foreach my $Mngl (keys(%Mangled))
4942 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004943 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4944 my $U2 = $tr_name{$Mngl};
4945 if($U1 ne $U2) {
4946 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004947 }
4948 }
4949}
4950
4951sub linkSymbol($)
4952{ # link symbols from shared libraries
4953 # with the symbols from header files
4954 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004955 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004956 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004957 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4958 or $EMERGENCY_MODE_48)
4959 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4960 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4961 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004962 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004963 {
4964 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4965 return correct_incharge($InfoId, $Version, $Mangled);
4966 }
4967 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004968 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004969 or not $BinaryOnly
4970 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004971 { # 1. --headers-only mode
4972 # 2. not mangled src-only symbols
4973 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4974 return $Mangled;
4975 }
4976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004977 }
4978 return "";
4979}
4980
4981sub setLanguage($$)
4982{
4983 my ($LibVersion, $Lang) = @_;
4984 if(not $UserLang) {
4985 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4986 }
4987}
4988
4989sub getSymbolInfo($)
4990{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004991 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004992 if(isInternal($InfoId)) {
4993 return;
4994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004995 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4996 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004997 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4998 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004999 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005000 return;
5001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005002 setFuncAccess($InfoId);
5003 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005004 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5005 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005006 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005007 return;
5008 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005009
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005010 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005011 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005012 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005013 if(not defined $TypeInfo{$Version}{$Return}
5014 or not $TypeInfo{$Version}{$Return}{"Name"})
5015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005016 delete($SymbolInfo{$Version}{$InfoId});
5017 return;
5018 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005019 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005020 }
5021 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5022 {
5023 if(defined $MissedTypedef{$Version}{$Rid})
5024 {
5025 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5026 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5027 }
5028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005030 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5031 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005032 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005033 my $Orig = getFuncOrig($InfoId);
5034 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005035 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5036 {
5037 delete($SymbolInfo{$Version}{$InfoId});
5038 return;
5039 }
5040
5041 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005043 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005044 return;
5045 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005046
5047 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005048 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005049 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5050
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005051 my @TParams = getTParams($Orig, "Func");
5052 if(not @TParams)
5053 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005054 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005055 return;
5056 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005057 foreach my $Pos (0 .. $#TParams)
5058 {
5059 my $Val = $TParams[$Pos];
5060 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5061
5062 if($Tmpl)
5063 {
5064 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5065 {
5066 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5067 }
5068 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005069 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005070
5071 if($Tmpl)
5072 {
5073 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5074 {
5075 if($Pos>$#TParams)
5076 {
5077 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5078 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5079 }
5080 }
5081 }
5082
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005083 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5084 { # operator<< <T>, operator>> <T>
5085 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5086 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005087 if(@TParams) {
5088 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5089 }
5090 else {
5091 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5092 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005093 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005094 }
5095 else
5096 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005097 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005098 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005099 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5100 {
5101 if($OSgroup eq "windows")
5102 { # cut the offset
5103 $MnglName=~s/\@\d+\Z//g;
5104 }
5105 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5106
5107 # NOTE: mangling of some symbols may change depending on GCC version
5108 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5109 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5110 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005111
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005112 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005113 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005114 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005115 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005116 return;
5117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005118 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005119 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005120 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005121 if($Skip)
5122 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005123 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005124 return;
5125 }
5126 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005127 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5128 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5129 }
5130
5131 if(set_Class_And_Namespace($InfoId))
5132 {
5133 delete($SymbolInfo{$Version}{$InfoId});
5134 return;
5135 }
5136
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005137 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5138 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005139 if(not defined $TypeInfo{$Version}{$ClassId}
5140 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5141 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005142 delete($SymbolInfo{$Version}{$InfoId});
5143 return;
5144 }
5145 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005146 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5147 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005148 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005149 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005150 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005151 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005152 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005153 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005154 }
5155 if($COMMON_LANGUAGE{$Version} eq "C++")
5156 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005157 # C++ or --headers-only mode
5158 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005159 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005160 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5161 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005163 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005164 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005165 if(my $Mangled = linkSymbol($InfoId)) {
5166 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005167 }
5168 }
5169 if($OStarget eq "windows")
5170 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005171 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005172 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005173 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005175 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005176 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005177 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005178 }
5179 }
5180 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005181 else
5182 { # not mangled in C
5183 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5184 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005185 if(not $CheckHeadersOnly
5186 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5187 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5188 {
5189 my $Incorrect = 0;
5190
5191 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5192 {
5193 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5194 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5195 { # mangled in the TU dump, but not mangled in the library
5196 $Incorrect = 1;
5197 }
5198 }
5199 else
5200 {
5201 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5202 { # all C++ functions are not mangled in the TU dump
5203 $Incorrect = 1;
5204 }
5205 }
5206 if($Incorrect)
5207 {
5208 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5209 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5210 }
5211 }
5212 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005213 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005214 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005215 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005216 return;
5217 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005218 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005219 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005220 { # identify virtual and pure virtual functions
5221 # NOTE: constructors cannot be virtual
5222 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5223 # in the TU dump, so taking it from the original symbol
5224 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5225 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5226 { # NOTE: D2 destructors are not present in a v-table
5227 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005229 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005230 if(isInline($InfoId)) {
5231 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005232 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005233 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005234 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5237 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005238 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005239 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005240 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005241 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005242 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005243 }
5244 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005245 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5246 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005247 if(not $ExtraDump)
5248 {
5249 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5250 { # non-target symbols
5251 delete($SymbolInfo{$Version}{$InfoId});
5252 return;
5253 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5257 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5258 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5259 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005260 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005261 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5262 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 return;
5265 }
5266 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005267 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005269 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005270 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005271 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005272 return;
5273 }
5274 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005275 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005276 }
5277 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005278 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5279 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5280 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005282 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5283 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005284 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005285 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005286 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005287 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005288 }
5289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005290 if(getFuncLink($InfoId) eq "Static") {
5291 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005292 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005293 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5294 {
5295 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5296 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005297 if($Unmangled=~/\.\_\d/)
5298 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005299 delete($SymbolInfo{$Version}{$InfoId});
5300 return;
5301 }
5302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005303 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005304
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005305 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5306 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005308 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5309 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005310 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005311
5312 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5313 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5314 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005315
5316 if($ExtraDump) {
5317 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5318 }
5319}
5320
5321sub guessHeader($)
5322{
5323 my $InfoId = $_[0];
5324 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5325 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5326 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5327 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5328 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5329 {
5330 if(get_filename($HPath) eq $Header)
5331 {
5332 my $HDir = get_filename(get_dirname($HPath));
5333 if($HDir ne "include"
5334 and $HDir=~/\A[a-z]+\Z/i) {
5335 return join_P($HDir, $Header);
5336 }
5337 }
5338 }
5339 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340}
5341
5342sub isInline($)
5343{ # "body: undefined" in the tree
5344 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005345 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5346 {
5347 if($Info=~/ undefined /i) {
5348 return 0;
5349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005350 }
5351 return 1;
5352}
5353
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005354sub hasThrow($)
5355{
5356 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5357 {
5358 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5359 return getTreeAttr_Unql($1, "unql");
5360 }
5361 }
5362 return 1;
5363}
5364
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005365sub getTypeId($)
5366{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005367 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5368 {
5369 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5370 return $1;
5371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005373 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005374}
5375
5376sub setTypeMemb($$)
5377{
5378 my ($TypeId, $TypeAttr) = @_;
5379 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005380 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005381 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005382 if($TypeType eq "Enum")
5383 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005384 my $MInfoId = getTreeAttr_Csts($TypeId);
5385 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005386 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005387 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5388 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005389 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005390 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5391 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005392 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005393 }
5394 }
5395 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5396 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005397 my $MInfoId = getTreeAttr_Flds($TypeId);
5398 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005399 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005400 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5401 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005402 if(not $IType or $IType ne "field_decl")
5403 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005404
5405 if($IType eq "var_decl")
5406 { # static field
5407 $StaticFields = 1;
5408 }
5409
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005410 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005411 next;
5412 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005413 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005414 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005415 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005416 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005417 }
5418 if(not $StructMembName)
5419 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005420 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005421 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005422 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005423 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5424 if(isAnon($UnnamedTName))
5425 { # rename unnamed fields to unnamed0, unnamed1, ...
5426 $StructMembName = "unnamed".($UnnamedPos++);
5427 }
5428 }
5429 }
5430 if(not $StructMembName)
5431 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005432 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005433 next;
5434 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005435 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005436 if(defined $MissedTypedef{$Version}{$MembTypeId})
5437 {
5438 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5439 $MembTypeId = $AddedTid;
5440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005442
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005443 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5444 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005445 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005446 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005447 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5448 }
5449 if($MInfo=~/spec:\s*mutable /)
5450 { # mutable fields
5451 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005452 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005453 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005454 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5455 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005456 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005457 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005458 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005459 }
5460 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005461 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005462 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5463 { # template
5464 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5465 }
5466 else {
5467 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005469 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005470
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005471 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005472 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005473 }
5474 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005475
5476 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005477}
5478
5479sub setFuncParams($)
5480{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005481 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005482 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005483
5484 my $FType = getFuncType($InfoId);
5485
5486 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005487 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005488 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5489 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005490 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005491 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005492 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5493 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005494 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005495 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5496 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005497 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005498 else
5499 { # skip
5500 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005501 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005502 # skip "this"-parameter
5503 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005505 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005506 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005507 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005508 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5509 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5510 if(not $ParamName)
5511 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005512 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005514 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5515 {
5516 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5517 $ParamTypeId = $AddedTid;
5518 }
5519 }
5520 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 if(not $PType or $PType eq "Unknown") {
5522 return 1;
5523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005524 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005525 if(not $PTName) {
5526 return 1;
5527 }
5528 if($PTName eq "void") {
5529 last;
5530 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005531 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005532 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005533 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005534 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005535 $ParamInfoId = getNextElem($ParamInfoId);
5536 next;
5537 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005538 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005539
5540 if(my %Base = get_BaseType($ParamTypeId, $Version))
5541 {
5542 if(defined $Base{"Template"}) {
5543 return 1;
5544 }
5545 }
5546
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005547 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005548 if(my $Algn = getAlgn($ParamInfoId)) {
5549 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5552 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005553 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005554 }
5555 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005556 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005557 if($ParamName ne "this" or $FType ne "Method") {
5558 $PPos += 1;
5559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005560 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005561 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005562 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 }
5564 return 0;
5565}
5566
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005567sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005568{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005569 my ($InfoId, $Vtt_Pos) = @_;
5570 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005571 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005572 my $FType = getFuncType($InfoId);
5573
5574 if($FType eq "Method")
5575 {
5576 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005577 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005578 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005579 if(not $ParamListElemId)
5580 { # foo(...)
5581 return 1;
5582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005583 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005584 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005585 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005586 { # actual params: may differ from formal args
5587 # formal int*const
5588 # actual: int*
5589 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005590 {
5591 $Vtt_Pos=-1;
5592 $ParamListElemId = getNextElem($ParamListElemId);
5593 next;
5594 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005595 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5596 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005597 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005598 $HaveVoid = 1;
5599 last;
5600 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005601 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005602 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005603 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5604 {
5605 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5606 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5607 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005608 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005609 }
5610 }
5611 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5612 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005613 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005614 { # params
5615 if($OldId ne $ParamTypeId)
5616 {
5617 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5618 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5619
5620 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5621 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5622 }
5623 }
5624 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005625 }
5626 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005627 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005628 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005629 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5630 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005631 if($PurpType eq "nop_expr")
5632 { # func ( const char* arg = (const char*)(void*)0 )
5633 $PurpId = getTreeAttr_Op($PurpId);
5634 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005635 my $Val = getInitVal($PurpId, $ParamTypeId);
5636 if(defined $Val) {
5637 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005639 }
5640 }
5641 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005642 if($Pos!=0 or $FType ne "Method") {
5643 $PPos += 1;
5644 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005645 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005646 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005647 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005648}
5649
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005650sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005651{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005652 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5653 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005654 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5655 return $1;
5656 }
5657 }
5658 return "";
5659}
5660
5661sub getTreeAttr_Chain($)
5662{
5663 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5664 {
5665 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5666 return $1;
5667 }
5668 }
5669 return "";
5670}
5671
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005672sub getTreeAttr_Unql($)
5673{
5674 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5675 {
5676 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5677 return $1;
5678 }
5679 }
5680 return "";
5681}
5682
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005683sub getTreeAttr_Scpe($)
5684{
5685 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5686 {
5687 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5688 return $1;
5689 }
5690 }
5691 return "";
5692}
5693
5694sub getTreeAttr_Type($)
5695{
5696 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5697 {
5698 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5699 return $1;
5700 }
5701 }
5702 return "";
5703}
5704
5705sub getTreeAttr_Name($)
5706{
5707 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5708 {
5709 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5710 return $1;
5711 }
5712 }
5713 return "";
5714}
5715
5716sub getTreeAttr_Mngl($)
5717{
5718 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5719 {
5720 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5721 return $1;
5722 }
5723 }
5724 return "";
5725}
5726
5727sub getTreeAttr_Prms($)
5728{
5729 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5730 {
5731 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5732 return $1;
5733 }
5734 }
5735 return "";
5736}
5737
5738sub getTreeAttr_Fncs($)
5739{
5740 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5741 {
5742 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5743 return $1;
5744 }
5745 }
5746 return "";
5747}
5748
5749sub getTreeAttr_Csts($)
5750{
5751 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5752 {
5753 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5754 return $1;
5755 }
5756 }
5757 return "";
5758}
5759
5760sub getTreeAttr_Purp($)
5761{
5762 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5763 {
5764 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5765 return $1;
5766 }
5767 }
5768 return "";
5769}
5770
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005771sub getTreeAttr_Op($)
5772{
5773 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5774 {
5775 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5776 return $1;
5777 }
5778 }
5779 return "";
5780}
5781
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005782sub getTreeAttr_Valu($)
5783{
5784 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5785 {
5786 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5787 return $1;
5788 }
5789 }
5790 return "";
5791}
5792
5793sub getTreeAttr_Flds($)
5794{
5795 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5796 {
5797 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5798 return $1;
5799 }
5800 }
5801 return "";
5802}
5803
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005804sub getTreeAttr_Binf($)
5805{
5806 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5807 {
5808 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5809 return $1;
5810 }
5811 }
5812 return "";
5813}
5814
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005815sub getTreeAttr_Args($)
5816{
5817 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5818 {
5819 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005820 return $1;
5821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005822 }
5823 return "";
5824}
5825
5826sub getTreeValue($)
5827{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005828 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5829 {
5830 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5831 return $1;
5832 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005833 }
5834 return "";
5835}
5836
5837sub getTreeAccess($)
5838{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005839 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005840 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005841 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5842 {
5843 my $Access = $1;
5844 if($Access eq "prot") {
5845 return "protected";
5846 }
5847 elsif($Access eq "priv") {
5848 return "private";
5849 }
5850 }
5851 elsif($Info=~/ protected /)
5852 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005853 return "protected";
5854 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005855 elsif($Info=~/ private /)
5856 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005857 return "private";
5858 }
5859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005860 return "public";
5861}
5862
5863sub setFuncAccess($)
5864{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005865 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005866 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005867 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005868 }
5869 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005870 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005871 }
5872}
5873
5874sub setTypeAccess($$)
5875{
5876 my ($TypeId, $TypeAttr) = @_;
5877 my $Access = getTreeAccess($TypeId);
5878 if($Access eq "protected") {
5879 $TypeAttr->{"Protected"} = 1;
5880 }
5881 elsif($Access eq "private") {
5882 $TypeAttr->{"Private"} = 1;
5883 }
5884}
5885
5886sub setFuncKind($)
5887{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005888 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5889 {
5890 if($Info=~/pseudo tmpl/) {
5891 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5892 }
5893 elsif($Info=~/ constructor /) {
5894 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5895 }
5896 elsif($Info=~/ destructor /) {
5897 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005899 }
5900}
5901
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005902sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005903{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005904 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5905 {
5906 if($Info=~/spec[ ]*:[ ]*pure /) {
5907 return "PureVirt";
5908 }
5909 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5910 return "Virt";
5911 }
5912 elsif($Info=~/ pure\s+virtual /)
5913 { # support for old GCC versions
5914 return "PureVirt";
5915 }
5916 elsif($Info=~/ virtual /)
5917 { # support for old GCC versions
5918 return "Virt";
5919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005920 }
5921 return "";
5922}
5923
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005924sub getFuncLink($)
5925{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005926 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5927 {
5928 if($Info=~/link[ ]*:[ ]*static /) {
5929 return "Static";
5930 }
5931 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005932 return $1;
5933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005934 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005935 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005936}
5937
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005938sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005939{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005940 my ($Symbol, $LibVersion) = @_;
5941 return "" if(not $Symbol or not $LibVersion);
5942 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5943 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005944 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005945 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5946 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5947 }
5948 }
5949 if($NS)
5950 {
5951 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5952 return $NS;
5953 }
5954 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005955 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005956 while($NS=~s/::[^:]+\Z//)
5957 {
5958 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5959 return $NS;
5960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005961 }
5962 }
5963 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005964
5965 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966}
5967
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005968sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005969{
5970 my ($TypeName, $LibVersion) = @_;
5971 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005972 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005973 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005974 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5975 return $NS;
5976 }
5977 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005978 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005979 while($NS=~s/::[^:]+\Z//)
5980 {
5981 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5982 return $NS;
5983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005984 }
5985 }
5986 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005987 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005988}
5989
5990sub getNameSpace($)
5991{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005992 my $InfoId = $_[0];
5993 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005994 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005995 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005997 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005998 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005999 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6000 {
6001 my $NameSpace = getTreeStr($1);
6002 if($NameSpace eq "::")
6003 { # global namespace
6004 return "";
6005 }
6006 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6007 $NameSpace = $BaseNameSpace."::".$NameSpace;
6008 }
6009 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6010 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006011 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006012 else {
6013 return "";
6014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006015 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006016 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006017 { # inside data type
6018 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6019 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006022 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006023 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024}
6025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026sub getEnumMembVal($)
6027{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6031 {
6032 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6033 {
6034 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6035 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6036 return getTreeValue($1);
6037 }
6038 else
6039 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6040 return getTreeValue($1);
6041 }
6042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006043 }
6044 }
6045 return "";
6046}
6047
6048sub getSize($)
6049{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006050 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6051 {
6052 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6053 return getTreeValue($1);
6054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006056 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057}
6058
6059sub getAlgn($)
6060{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006061 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6062 {
6063 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6064 return $1;
6065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006067 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068}
6069
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006070sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006072 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6073 {
6074 if($Info=~/ bitfield /) {
6075 return getSize($_[0]);
6076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006077 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006078 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006079}
6080
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006081sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006082{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006083 if(my $Chan = getTreeAttr_Chan($_[0])) {
6084 return $Chan;
6085 }
6086 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6087 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006088 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006089 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006090}
6091
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006092sub registerHeader($$)
6093{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006094 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006095 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006096 return "";
6097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006098 if(is_abs($Header) and not -f $Header)
6099 { # incorrect absolute path
6100 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006101 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006102 if(skipHeader($Header, $LibVersion))
6103 { # skip
6104 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006106 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6107 {
6108 detect_header_includes($Header_Path, $LibVersion);
6109
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006110 if(defined $Tolerance and $Tolerance=~/3/)
6111 { # 3 - skip headers that include non-Linux headers
6112 if($OSgroup ne "windows")
6113 {
6114 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6115 {
6116 if(specificHeader($Inc, "windows")) {
6117 return "";
6118 }
6119 }
6120 }
6121 }
6122
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006123 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6124 { # redirect
6125 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6126 or skipHeader($RHeader_Path, $LibVersion))
6127 { # skip
6128 return "";
6129 }
6130 $Header_Path = $RHeader_Path;
6131 }
6132 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6133 { # skip
6134 return "";
6135 }
6136
6137 if(my $HName = get_filename($Header_Path))
6138 { # register
6139 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6140 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6141 }
6142
6143 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6144 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006145 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006146 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006147 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006148 }
6149
6150 if($CheckHeadersOnly
6151 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6152 { # /usr/include/c++/4.6.1/...
6153 $STDCXX_TESTING = 1;
6154 }
6155
6156 return $Header_Path;
6157 }
6158 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006159}
6160
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006161sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006162{
6163 my ($Dir, $WithDeps, $LibVersion) = @_;
6164 $Dir=~s/[\/\\]+\Z//g;
6165 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006166 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006168 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006169 if($WithDeps)
6170 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006171 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6172 return;
6173 }
6174 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6175 $Mode = "DepsOnly";
6176 }
6177 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006178 else
6179 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006180 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6181 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6182 return;
6183 }
6184 }
6185 $Header_Dependency{$LibVersion}{$Dir} = 1;
6186 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6187 if($Mode eq "DepsOnly")
6188 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006189 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006190 $Header_Dependency{$LibVersion}{$Path} = 1;
6191 }
6192 return;
6193 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006194 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006195 {
6196 if($WithDeps)
6197 {
6198 my $SubDir = $Path;
6199 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6200 { # register all sub directories
6201 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6202 }
6203 }
6204 next if(is_not_header($Path));
6205 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006206 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006207 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006208 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6209 }
6210 }
6211 if(get_filename($Dir) eq "include")
6212 { # search for "lib/include/" directory
6213 my $LibDir = $Dir;
6214 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006215 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006216 }
6217 }
6218}
6219
6220sub parse_redirect($$$)
6221{
6222 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006223 my @Errors = ();
6224 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6225 push(@Errors, $1);
6226 }
6227 my $Redirect = "";
6228 foreach (@Errors)
6229 {
6230 s/\s{2,}/ /g;
6231 if(/(only|must\ include
6232 |update\ to\ include
6233 |replaced\ with
6234 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006235 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006236 {
6237 $Redirect = $2;
6238 last;
6239 }
6240 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6241 {
6242 $Redirect = $2;
6243 last;
6244 }
6245 elsif(/this\ header\ should\ not\ be\ used
6246 |programs\ should\ not\ directly\ include
6247 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6248 |is\ not\ supported\ API\ for\ general\ use
6249 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006250 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006251 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6252 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6253 }
6254 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006255 if($Redirect)
6256 {
6257 $Redirect=~s/\A<//g;
6258 $Redirect=~s/>\Z//g;
6259 }
6260 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006261}
6262
6263sub parse_includes($$)
6264{
6265 my ($Content, $Path) = @_;
6266 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006267 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006268 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006269 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006270 my $Method = substr($Header, 0, 1, "");
6271 substr($Header, length($Header)-1, 1, "");
6272 $Header = path_format($Header, $OSgroup);
6273 if($Method eq "\"" or is_abs($Header))
6274 {
6275 if(-e join_P(get_dirname($Path), $Header))
6276 { # relative path exists
6277 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006278 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006279 else
6280 { # include "..." that doesn't exist is equal to include <...>
6281 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006283 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006284 else {
6285 $Includes{$Header} = 1;
6286 }
6287 }
6288 if($ExtraInfo)
6289 {
6290 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6291 { # FT_FREETYPE_H
6292 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006293 }
6294 }
6295 return \%Includes;
6296}
6297
6298sub ignore_path($)
6299{
6300 my $Path = $_[0];
6301 if($Path=~/\~\Z/)
6302 {# skipping system backup files
6303 return 1;
6304 }
6305 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6306 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6307 return 1;
6308 }
6309 return 0;
6310}
6311
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006312sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006313{
6314 my ($ArrRef, $W) = @_;
6315 return if(length($W)<2);
6316 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6317}
6318
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006319sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006320{
6321 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006322
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006323 $H1=~s/\.[a-z]+\Z//ig;
6324 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006325
6326 my $Hname1 = get_filename($H1);
6327 my $Hname2 = get_filename($H2);
6328 my $HDir1 = get_dirname($H1);
6329 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006330 my $Dirname1 = get_filename($HDir1);
6331 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006332
6333 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6334 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6335
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006336 if($_[0] eq $_[1]
6337 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 return 0;
6339 }
6340 elsif($H1=~/\A\Q$H2\E/) {
6341 return 1;
6342 }
6343 elsif($H2=~/\A\Q$H1\E/) {
6344 return -1;
6345 }
6346 elsif($HDir1=~/\Q$Hname1\E/i
6347 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006348 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006349 return -1;
6350 }
6351 elsif($HDir2=~/\Q$Hname2\E/i
6352 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006353 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006354 return 1;
6355 }
6356 elsif($Hname1=~/\Q$Dirname1\E/i
6357 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006358 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006359 return -1;
6360 }
6361 elsif($Hname2=~/\Q$Dirname2\E/i
6362 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006363 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006364 return 1;
6365 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006366 elsif($Hname1=~/(config|lib|util)/i
6367 and $Hname2!~/(config|lib|util)/i)
6368 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006369 return -1;
6370 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006371 elsif($Hname2=~/(config|lib|util)/i
6372 and $Hname1!~/(config|lib|util)/i)
6373 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006374 return 1;
6375 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006376 else
6377 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006378 my $R1 = checkRelevance($H1);
6379 my $R2 = checkRelevance($H2);
6380 if($R1 and not $R2)
6381 { # libebook/e-book.h
6382 return -1;
6383 }
6384 elsif($R2 and not $R1)
6385 { # libebook/e-book.h
6386 return 1;
6387 }
6388 else
6389 {
6390 return (lc($H1) cmp lc($H2));
6391 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006392 }
6393}
6394
6395sub searchForHeaders($)
6396{
6397 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006398
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006400 registerGccHeaders();
6401
6402 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6403 { # c++ standard include paths
6404 registerCppHeaders();
6405 }
6406
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006407 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006408 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6409 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006410 {
6411 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006412 if($SystemRoot)
6413 {
6414 if(is_abs($Path)) {
6415 $Path = $SystemRoot.$Path;
6416 }
6417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006418 if(not -e $Path) {
6419 exitStatus("Access_Error", "can't access \'$Path\'");
6420 }
6421 elsif(-f $Path) {
6422 exitStatus("Access_Error", "\'$Path\' - not a directory");
6423 }
6424 elsif(-d $Path)
6425 {
6426 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006427 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006428 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6429 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006430 }
6431 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006432 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 }
6434 }
6435 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006436 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6438 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006440 # registering directories
6441 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6442 {
6443 next if(not -e $Path);
6444 $Path = get_abs_path($Path);
6445 $Path = path_format($Path, $OSgroup);
6446 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006447 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006448 }
6449 elsif(-f $Path)
6450 {
6451 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006452 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006453 and not $LocalIncludes{$Dir})
6454 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006455 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006456 # if(my $OutDir = get_dirname($Dir))
6457 # { # registering the outer directory
6458 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6459 # and not $LocalIncludes{$OutDir}) {
6460 # registerDir($OutDir, 0, $LibVersion);
6461 # }
6462 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006463 }
6464 }
6465 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006466
6467 # clean memory
6468 %RegisteredDirs = ();
6469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006470 # registering headers
6471 my $Position = 0;
6472 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6473 {
6474 if(is_abs($Dest) and not -e $Dest) {
6475 exitStatus("Access_Error", "can't access \'$Dest\'");
6476 }
6477 $Dest = path_format($Dest, $OSgroup);
6478 if(is_header($Dest, 1, $LibVersion))
6479 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006480 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006481 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6482 }
6483 }
6484 elsif(-d $Dest)
6485 {
6486 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006487 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006488 {
6489 next if(ignore_path($Path));
6490 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006491 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006492 push(@Registered, $HPath);
6493 }
6494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006495 @Registered = sort {sortHeaders($a, $b)} @Registered;
6496 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006497 foreach my $Path (@Registered) {
6498 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6499 }
6500 }
6501 else {
6502 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6503 }
6504 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006505
6506 if(defined $Tolerance and $Tolerance=~/4/)
6507 { # 4 - skip headers included by others
6508 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6509 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006510 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006511 delete($Registered_Headers{$LibVersion}{$Path});
6512 }
6513 }
6514 }
6515
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006516 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6517 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006518 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006519 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006520 if(is_abs($Header) and not -f $Header) {
6521 exitStatus("Access_Error", "can't access file \'$Header\'");
6522 }
6523 $Header = path_format($Header, $OSgroup);
6524 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6525 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006526 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006527 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006528 }
6529 else {
6530 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 }
6533 }
6534 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6535 { # set relative paths (for duplicates)
6536 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6537 { # search for duplicates
6538 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6539 my $Prefix = get_dirname($FirstPath);
6540 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6541 { # detect a shortest distinguishing prefix
6542 my $NewPrefix = $1;
6543 my %Identity = ();
6544 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6545 {
6546 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6547 $Identity{$Path} = $1;
6548 }
6549 }
6550 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6551 { # all names are differend with current prefix
6552 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6553 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6554 }
6555 last;
6556 }
6557 $Prefix = $NewPrefix; # increase prefix
6558 }
6559 }
6560 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006561
6562 # clean memory
6563 %HeaderName_Paths = ();
6564
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006565 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6566 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006567 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006568 my ($Pos, $PairPos) = (-1, -1);
6569 my ($Path, $PairPath) = ();
6570 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6571 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6572 foreach my $Header_Path (@Paths)
6573 {
6574 if(get_filename($Header_Path) eq $PairName)
6575 {
6576 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6577 $PairPath = $Header_Path;
6578 }
6579 if(get_filename($Header_Path) eq $HeaderName)
6580 {
6581 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6582 $Path = $Header_Path;
6583 }
6584 }
6585 if($PairPos!=-1 and $Pos!=-1
6586 and int($PairPos)<int($Pos))
6587 {
6588 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6589 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6590 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6591 }
6592 }
6593 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6594 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6595 }
6596}
6597
6598sub detect_real_includes($$)
6599{
6600 my ($AbsPath, $LibVersion) = @_;
6601 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6602 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6603 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6604 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6605 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006606 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6607
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006608 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6609 return () if(not $Path);
6610 open(PREPROC, $Path);
6611 while(<PREPROC>)
6612 {
6613 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6614 {
6615 my $Include = path_format($1, $OSgroup);
6616 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6617 next;
6618 }
6619 if($Include eq $AbsPath) {
6620 next;
6621 }
6622 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6623 }
6624 }
6625 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006626 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6627}
6628
6629sub detect_header_includes($$)
6630{
6631 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006632 return if(not $LibVersion or not $Path);
6633 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6634 return;
6635 }
6636 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6637
6638 if(not -e $Path) {
6639 return;
6640 }
6641
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006642 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006643 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6644 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006645 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006646 {
6647 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006648 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006649 }
6650 if($RedirectPath ne $Path) {
6651 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6652 }
6653 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006654 else
6655 { # can't find
6656 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006658 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006659 if(my $Inc = parse_includes($Content, $Path))
6660 {
6661 foreach my $Include (keys(%{$Inc}))
6662 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006663 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006664
6665 if(defined $Tolerance and $Tolerance=~/4/)
6666 {
6667 if(my $HPath = identifyHeader($Include, $LibVersion))
6668 {
6669 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6670 }
6671 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006674}
6675
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006676sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006677{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006678 my $Path = $_[0];
6679 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006680 if($OStarget eq "symbian")
6681 {
6682 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6683 { # epoc32/include/libc/{stdio, ...}.h
6684 return 1;
6685 }
6686 }
6687 else
6688 {
6689 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6690 { # /usr/include/{stdio, ...}.h
6691 return 1;
6692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006694 return 0;
6695}
6696
6697sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006698{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006699 my $Dir = $_[0];
6700 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006701 if($OStarget eq "symbian")
6702 {
6703 if(get_filename($OutDir) eq "libc"
6704 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6705 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6706 return 1;
6707 }
6708 }
6709 else
6710 { # linux
6711 if($OutDir eq "/usr/include"
6712 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6713 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6714 return 1;
6715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006716 }
6717 return 0;
6718}
6719
6720sub detect_recursive_includes($$)
6721{
6722 my ($AbsPath, $LibVersion) = @_;
6723 return () if(not $AbsPath);
6724 if(isCyclical(\@RecurInclude, $AbsPath)) {
6725 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6726 }
6727 my ($AbsDir, $Name) = separate_path($AbsPath);
6728 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006729 { # system GLIBC internals
6730 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006731 }
6732 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6733 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6734 }
6735 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006736
6737 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6738 { # skip /usr/include/c++/*/ headers
6739 return () if(not $ExtraInfo);
6740 }
6741
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006742 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006743 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006744 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006745 { # check "real" (non-"model") include paths
6746 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6747 pop(@RecurInclude);
6748 return @Paths;
6749 }
6750 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6751 detect_header_includes($AbsPath, $LibVersion);
6752 }
6753 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6754 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006755 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006756 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006757 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006758 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006759 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006760 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006761 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006762 }
6763 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006764 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006765 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006766 { # search for the nearest header
6767 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006768 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006769 if(-f $Candidate) {
6770 $HPath = $Candidate;
6771 }
6772 }
6773 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006774 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 }
6776 next if(not $HPath);
6777 if($HPath eq $AbsPath) {
6778 next;
6779 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006780
6781 if($Debug)
6782 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006783# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6784# {
6785# print STDERR "$AbsPath -> $HPath\n";
6786# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006787 }
6788
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006789 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6790 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006791 { # only include <...>, skip include "..." prefixes
6792 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6793 }
6794 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6795 {
6796 if($IncPath eq $AbsPath) {
6797 next;
6798 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006799 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6800 if($RIncType==-1)
6801 { # include "..."
6802 $RIncType = $IncType;
6803 }
6804 elsif($RIncType==2)
6805 {
6806 if($IncType!=-1) {
6807 $RIncType = $IncType;
6808 }
6809 }
6810 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006811 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6812 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6813 }
6814 }
6815 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6816 {
6817 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6818 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6819 { # distinguish math.h from glibc and math.h from the tested library
6820 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6821 last;
6822 }
6823 }
6824 }
6825 pop(@RecurInclude);
6826 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6827}
6828
6829sub find_in_framework($$$)
6830{
6831 my ($Header, $Framework, $LibVersion) = @_;
6832 return "" if(not $Header or not $Framework or not $LibVersion);
6833 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6834 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6835 }
6836 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6837 {
6838 if(get_filename($Dependency) eq $Framework
6839 and -f get_dirname($Dependency)."/".$Header) {
6840 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6841 }
6842 }
6843 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6844}
6845
6846sub find_in_defaults($)
6847{
6848 my $Header = $_[0];
6849 return "" if(not $Header);
6850 if(defined $Cache{"find_in_defaults"}{$Header}) {
6851 return $Cache{"find_in_defaults"}{$Header};
6852 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006853 foreach my $Dir (@DefaultIncPaths,
6854 @DefaultGccPaths,
6855 @DefaultCppPaths,
6856 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006857 {
6858 next if(not $Dir);
6859 if(-f $Dir."/".$Header) {
6860 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6861 }
6862 }
6863 return ($Cache{"find_in_defaults"}{$Header}="");
6864}
6865
6866sub cmp_paths($$)
6867{
6868 my ($Path1, $Path2) = @_;
6869 my @Parts1 = split(/[\/\\]/, $Path1);
6870 my @Parts2 = split(/[\/\\]/, $Path2);
6871 foreach my $Num (0 .. $#Parts1)
6872 {
6873 my $Part1 = $Parts1[$Num];
6874 my $Part2 = $Parts2[$Num];
6875 if($GlibcDir{$Part1}
6876 and not $GlibcDir{$Part2}) {
6877 return 1;
6878 }
6879 elsif($GlibcDir{$Part2}
6880 and not $GlibcDir{$Part1}) {
6881 return -1;
6882 }
6883 elsif($Part1=~/glib/
6884 and $Part2!~/glib/) {
6885 return 1;
6886 }
6887 elsif($Part1!~/glib/
6888 and $Part2=~/glib/) {
6889 return -1;
6890 }
6891 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6892 return $CmpRes;
6893 }
6894 }
6895 return 0;
6896}
6897
6898sub checkRelevance($)
6899{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006900 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006901 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006902
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006903 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006904 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006905 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006906
6907 my $Name = lc(get_filename($Path));
6908 my $Dir = lc(get_dirname($Path));
6909
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006910 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006911
6912 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006913 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006914 my $Len = length($Token);
6915 next if($Len<=1);
6916 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6917 { # include/evolution-data-server-1.4/libebook/e-book.h
6918 return 1;
6919 }
6920 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006921 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006922 return 1;
6923 }
6924 }
6925 return 0;
6926}
6927
6928sub checkFamily(@)
6929{
6930 my @Paths = @_;
6931 return 1 if($#Paths<=0);
6932 my %Prefix = ();
6933 foreach my $Path (@Paths)
6934 {
6935 if($SystemRoot) {
6936 $Path = cut_path_prefix($Path, $SystemRoot);
6937 }
6938 if(my $Dir = get_dirname($Path))
6939 {
6940 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6941 $Prefix{$Dir} += 1;
6942 $Prefix{get_dirname($Dir)} += 1;
6943 }
6944 }
6945 foreach (sort keys(%Prefix))
6946 {
6947 if(get_depth($_)>=3
6948 and $Prefix{$_}==$#Paths+1) {
6949 return 1;
6950 }
6951 }
6952 return 0;
6953}
6954
6955sub isAcceptable($$$)
6956{
6957 my ($Header, $Candidate, $LibVersion) = @_;
6958 my $HName = get_filename($Header);
6959 if(get_dirname($Header))
6960 { # with prefix
6961 return 1;
6962 }
6963 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6964 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6965 return 1;
6966 }
6967 if(checkRelevance($Candidate))
6968 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6969 return 1;
6970 }
6971 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6972 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6973 # /usr/include/qt4/Qt/qsslconfiguration.h
6974 return 1;
6975 }
6976 if($OStarget eq "symbian")
6977 {
6978 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6979 return 1;
6980 }
6981 }
6982 return 0;
6983}
6984
6985sub isRelevant($$$)
6986{ # disallow to search for "abstract" headers in too deep directories
6987 my ($Header, $Candidate, $LibVersion) = @_;
6988 my $HName = get_filename($Header);
6989 if($OStarget eq "symbian")
6990 {
6991 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6992 return 0;
6993 }
6994 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006995 if($OStarget ne "bsd")
6996 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006997 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6998 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6999 return 0;
7000 }
7001 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007002 if($OStarget ne "windows")
7003 {
7004 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7005 { # skip /usr/include/wine/msvcrt
7006 return 0;
7007 }
7008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007009 if(not get_dirname($Header)
7010 and $Candidate=~/[\/\\]wx[\/\\]/)
7011 { # do NOT search in system /wx/ directory
7012 # for headers without a prefix: sstream.h
7013 return 0;
7014 }
7015 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7016 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7017 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7018 return 0;
7019 }
7020 if($Candidate=~/[\/\\]asm-/
7021 and (my $Arch = getArch($LibVersion)) ne "unknown")
7022 { # arch-specific header files
7023 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7024 {# skip ../asm-arm/ if using x86 architecture
7025 return 0;
7026 }
7027 }
7028 my @Candidates = getSystemHeaders($HName, $LibVersion);
7029 if($#Candidates==1)
7030 { # unique header
7031 return 1;
7032 }
7033 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7034 if($#SCandidates==1)
7035 { # unique name
7036 return 1;
7037 }
7038 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7039 if(get_depth($Candidate)-$SystemDepth>=5)
7040 { # abstract headers in too deep directories
7041 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7042 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7043 return 0;
7044 }
7045 }
7046 if($Header eq "parser.h"
7047 and $Candidate!~/\/libxml2\//)
7048 { # select parser.h from xml2 library
7049 return 0;
7050 }
7051 if(not get_dirname($Header)
7052 and keys(%{$SystemHeaders{$HName}})>=3)
7053 { # many headers with the same name
7054 # like thread.h included without a prefix
7055 if(not checkFamily(@Candidates)) {
7056 return 0;
7057 }
7058 }
7059 return 1;
7060}
7061
7062sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007063{ # cache function
7064 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7065 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7066 }
7067 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7068}
7069
7070sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007071{
7072 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007073 if(-f $Header) {
7074 return $Header;
7075 }
7076 if(is_abs($Header) and not -f $Header)
7077 { # incorrect absolute path
7078 return "";
7079 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007080 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007081 { # too abstract configuration headers
7082 return "";
7083 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007084 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007085 if($OSgroup ne "windows")
7086 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007087 if(defined $WinHeaders{lc($HName)}
7088 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007089 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007090 return "";
7091 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007092 }
7093 if($OSgroup ne "macos")
7094 {
7095 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007096 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007097 return "";
7098 }
7099 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007100
7101 if(defined $ObsoleteHeaders{$HName})
7102 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007103 return "";
7104 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007105 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7106 {
7107 if(defined $AlienHeaders{$HName}
7108 or defined $AlienHeaders{$Header})
7109 { # alien headers from other systems
7110 return "";
7111 }
7112 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007113
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007114 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007115 { # search in default paths
7116 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007117 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007118 }
7119 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007120 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007121 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007122 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007123 }
7124 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7125 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7126 {
7127 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007128 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007129 }
7130 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007131 # error
7132 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007133}
7134
7135sub getSystemHeaders($$)
7136{
7137 my ($Header, $LibVersion) = @_;
7138 my @Candidates = ();
7139 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7140 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007141 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007142 next;
7143 }
7144 push(@Candidates, $Candidate);
7145 }
7146 return @Candidates;
7147}
7148
7149sub cut_path_prefix($$)
7150{
7151 my ($Path, $Prefix) = @_;
7152 return $Path if(not $Prefix);
7153 $Prefix=~s/[\/\\]+\Z//;
7154 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7155 return $Path;
7156}
7157
7158sub is_default_include_dir($)
7159{
7160 my $Dir = $_[0];
7161 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007162 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163}
7164
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007165sub identifyHeader($$)
7166{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007167 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007168 if(not $Header) {
7169 return "";
7170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007171 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007172 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7173 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007174 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007175 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007176}
7177
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007178sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007179{ # search for header by absolute path, relative path or name
7180 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007181 if(-f $Header)
7182 { # it's relative or absolute path
7183 return get_abs_path($Header);
7184 }
7185 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7186 and my $HeaderDir = find_in_defaults($Header))
7187 { # search for libc headers in the /usr/include
7188 # for non-libc target library before searching
7189 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007190 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191 }
7192 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7193 { # search in the target library paths
7194 return $Path;
7195 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007196 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197 { # search in the internal GCC include paths
7198 return $DefaultGccHeader{$Header};
7199 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007200 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007202 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007203 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007204 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007205 { # search in the default G++ include paths
7206 return $DefaultCppHeader{$Header};
7207 }
7208 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7209 { # search everywhere in the system
7210 return $AnyPath;
7211 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007212 elsif($OSgroup eq "macos")
7213 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7214 if(my $Dir = get_dirname($Header))
7215 {
7216 my $RelPath = "Headers\/".get_filename($Header);
7217 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007218 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007219 }
7220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007222 # cannot find anything
7223 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224}
7225
7226sub getLocation($)
7227{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007228 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7229 {
7230 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007231 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007233 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007234 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235}
7236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007237sub getNameByInfo($)
7238{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007239 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007240 {
7241 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7242 {
7243 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7244 {
7245 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7246 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007247 my $Str = $1;
7248 if($CppMode{$Version}
7249 and $Str=~/\Ac99_(.+)\Z/)
7250 {
7251 if($CppKeywords_A{$1}) {
7252 $Str=$1;
7253 }
7254 }
7255 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007256 }
7257 }
7258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007260 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007261}
7262
7263sub getTreeStr($)
7264{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007265 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007266 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007267 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7268 {
7269 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007270 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007271 and $Str=~/\Ac99_(.+)\Z/)
7272 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007273 if($CppKeywords_A{$1}) {
7274 $Str=$1;
7275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007276 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007277 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007280 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281}
7282
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007283sub getFuncShortName($)
7284{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007285 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007286 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007287 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007288 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007289 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007290 {
7291 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7292 {
7293 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7294 return "operator ".$RName;
7295 }
7296 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 }
7298 else
7299 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007300 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7301 {
7302 if(my $Ind = $Operator_Indication{$1}) {
7303 return "operator".$Ind;
7304 }
7305 elsif(not $UnknownOperator{$1})
7306 {
7307 printMsg("WARNING", "unknown operator $1");
7308 $UnknownOperator{$1} = 1;
7309 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007310 }
7311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007312 }
7313 else
7314 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007315 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7316 return getTreeStr($1);
7317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007318 }
7319 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007320 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321}
7322
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007323sub getFuncReturn($)
7324{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007325 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7326 {
7327 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7328 {
7329 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7330 return $1;
7331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007332 }
7333 }
7334 return "";
7335}
7336
7337sub getFuncOrig($)
7338{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007339 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7340 {
7341 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7342 return $1;
7343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007344 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007345 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007346}
7347
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007348sub unmangleArray(@)
7349{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007350 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351 { # MSVC mangling
7352 my $UndNameCmd = get_CmdPath("undname");
7353 if(not $UndNameCmd) {
7354 exitStatus("Not_Found", "can't find \"undname\"");
7355 }
7356 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007357 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007358 }
7359 else
7360 { # GCC mangling
7361 my $CppFiltCmd = get_CmdPath("c++filt");
7362 if(not $CppFiltCmd) {
7363 exitStatus("Not_Found", "can't find c++filt in PATH");
7364 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007365 if(not defined $CPPFILT_SUPPORT_FILE)
7366 {
7367 my $Info = `$CppFiltCmd -h 2>&1`;
7368 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7369 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007370 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007371 if($CPPFILT_SUPPORT_FILE)
7372 { # new versions of c++filt can take a file
7373 if($#_>$MAX_CPPFILT_FILE_SIZE)
7374 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7375 # this is fixed in the oncoming version of Binutils
7376 my @Half = splice(@_, 0, ($#_+1)/2);
7377 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007379 else
7380 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007381 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7382 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7383 if($?==139)
7384 { # segmentation fault
7385 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7386 }
7387 return split(/\n/, $Res);
7388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007389 }
7390 else
7391 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007392 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7393 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007394 my @Half = splice(@_, 0, ($#_+1)/2);
7395 return (unmangleArray(@Half), unmangleArray(@_))
7396 }
7397 else
7398 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007400 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7401 if($?==139)
7402 { # segmentation fault
7403 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7404 }
7405 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 }
7407 }
7408 }
7409}
7410
7411sub get_SignatureNoInfo($$)
7412{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007413 my ($Symbol, $LibVersion) = @_;
7414 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7415 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007417 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007418 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007419 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007421 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007422 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7423 $Signature=~s/\Qstd::map<std::string, std::string, std::less<std::string >, std::allocator<std::pair<std::string const, std::string > > >\E/std::map<std::string, std::string>/g;
7424 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007425 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007426 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007427 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007428 $Signature .= " [data]";
7429 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007430 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007431 $Signature .= " (...)";
7432 }
7433 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007434 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007435 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007436 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007437 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7438 }
7439 if($SymbolVersion) {
7440 $Signature .= $VersionSpec.$SymbolVersion;
7441 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007442 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007443}
7444
7445sub get_ChargeLevel($$)
7446{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007447 my ($Symbol, $LibVersion) = @_;
7448 return "" if($Symbol!~/\A(_Z|\?)/);
7449 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7450 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007452 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007454 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007455 return "[in-charge]";
7456 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007457 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 return "[not-in-charge]";
7459 }
7460 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007461 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007463 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007464 return "[in-charge]";
7465 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007466 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007467 return "[not-in-charge]";
7468 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007469 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 return "[in-charge-deleting]";
7471 }
7472 }
7473 }
7474 else
7475 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007476 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007477 return "[in-charge]";
7478 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007479 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007480 return "[not-in-charge]";
7481 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007482 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007483 return "[in-charge]";
7484 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007485 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007486 return "[not-in-charge]";
7487 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007488 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007489 return "[in-charge-deleting]";
7490 }
7491 }
7492 return "";
7493}
7494
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007495sub get_Signature_M($$)
7496{
7497 my ($Symbol, $LibVersion) = @_;
7498 my $Signature_M = $tr_name{$Symbol};
7499 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7500 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007501 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007502 }
7503 return $Signature_M;
7504}
7505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506sub get_Signature($$)
7507{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007508 my ($Symbol, $LibVersion) = @_;
7509 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7510 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007511 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007512 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7513 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007514 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007515 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007516 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007517 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007518 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7519 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007521 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7522 {
7523 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7524 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7525 $Signature .= "~";
7526 }
7527 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007529 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007530 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007531 }
7532 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007533 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007534 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007535 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7536 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007538 else
7539 {
7540 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007541 }
7542 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 {
7545 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007546 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007548 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007549 if(not $ParamTypeName) {
7550 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7551 }
7552 foreach my $Typedef (keys(%ChangedTypedef))
7553 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007554 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7555 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007558 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7559 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007560 if($ParamName eq "this"
7561 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007562 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007563 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007564 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007565 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007566 }
7567 else {
7568 push(@ParamArray, $ParamTypeName);
7569 }
7570 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007571 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7572 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007573 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007574 }
7575 else
7576 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007577 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007578 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007579 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007580 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007581 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007582 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7583 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007584 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007586 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7587 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007588 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007590 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7591 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007592 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007593 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594 }
7595 }
7596 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007597 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007598 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007599 }
7600 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007601 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007602 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007603 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604}
7605
7606sub create_member_decl($$)
7607{
7608 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007609 if($TName=~/\([\*]+\)/)
7610 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007611 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7612 return $TName;
7613 }
7614 else
7615 {
7616 my @ArraySizes = ();
7617 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7618 push(@ArraySizes, $1);
7619 }
7620 return $TName." ".$Member.join("", @ArraySizes);
7621 }
7622}
7623
7624sub getFuncType($)
7625{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007626 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7627 {
7628 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7629 {
7630 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7631 {
7632 if($Type eq "method_type") {
7633 return "Method";
7634 }
7635 elsif($Type eq "function_type") {
7636 return "Function";
7637 }
7638 else {
7639 return "Other";
7640 }
7641 }
7642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007643 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007644 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007645}
7646
7647sub getFuncTypeId($)
7648{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007649 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7650 {
7651 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7652 return $1;
7653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007655 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007656}
7657
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007658sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007659{ # "._N" or "$_N" in older GCC versions
7660 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007661}
7662
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007663sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007664{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007665 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7666 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007667 }
7668
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007669 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007670
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007671 if($_[1] ne "S")
7672 {
7673 $N=~s/\A[ ]+//g;
7674 $N=~s/[ ]+\Z//g;
7675 $N=~s/[ ]{2,}/ /g;
7676 }
7677
7678 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007679
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007680 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007681
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007682 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7683 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007684
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007685 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007686
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007687 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007688
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007689 if($_[1] eq "S")
7690 {
7691 if(index($N, "operator")!=-1) {
7692 $N=~s/\b(operator[ ]*)> >/$1>>/;
7693 }
7694 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007695
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007696 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007697}
7698
7699sub get_HeaderDeps($$)
7700{
7701 my ($AbsPath, $LibVersion) = @_;
7702 return () if(not $AbsPath or not $LibVersion);
7703 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7704 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7705 }
7706 my %IncDir = ();
7707 detect_recursive_includes($AbsPath, $LibVersion);
7708 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7709 {
7710 next if(not $HeaderPath);
7711 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7712 my $Dir = get_dirname($HeaderPath);
7713 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7714 {
7715 my $Dep = $Dir;
7716 if($Prefix)
7717 {
7718 if($OSgroup eq "windows")
7719 { # case insensitive seach on windows
7720 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7721 next;
7722 }
7723 }
7724 elsif($OSgroup eq "macos")
7725 { # seach in frameworks
7726 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7727 {
7728 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7729 {# frameworks
7730 my ($HFramework, $HName) = ($1, $2);
7731 $Dep = $HFramework;
7732 }
7733 else
7734 {# mismatch
7735 next;
7736 }
7737 }
7738 }
7739 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7740 { # Linux, FreeBSD
7741 next;
7742 }
7743 }
7744 if(not $Dep)
7745 { # nothing to include
7746 next;
7747 }
7748 if(is_default_include_dir($Dep))
7749 { # included by the compiler
7750 next;
7751 }
7752 if(get_depth($Dep)==1)
7753 { # too short
7754 next;
7755 }
7756 if(isLibcDir($Dep))
7757 { # do NOT include /usr/include/{sys,bits}
7758 next;
7759 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007760 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007761 }
7762 }
7763 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7764 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7765}
7766
7767sub sortIncPaths($$)
7768{
7769 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007770 if(not $ArrRef or $#{$ArrRef}<0) {
7771 return $ArrRef;
7772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007773 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7774 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007775 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007776 return $ArrRef;
7777}
7778
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007779sub sortDeps($$$)
7780{
7781 if($Header_Dependency{$_[2]}{$_[0]}
7782 and not $Header_Dependency{$_[2]}{$_[1]}) {
7783 return 1;
7784 }
7785 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7786 and $Header_Dependency{$_[2]}{$_[1]}) {
7787 return -1;
7788 }
7789 return 0;
7790}
7791
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007792sub join_P($$)
7793{
7794 my $S = "/";
7795 if($OSgroup eq "windows") {
7796 $S = "\\";
7797 }
7798 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007799}
7800
7801sub get_namespace_additions($)
7802{
7803 my $NameSpaces = $_[0];
7804 my ($Additions, $AddNameSpaceId) = ("", 1);
7805 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7806 {
7807 next if($SkipNameSpaces{$Version}{$NS});
7808 next if(not $NS or $NameSpaces->{$NS}==-1);
7809 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7810 next if($NS=~/\A__/i);
7811 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007812 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007813 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7814 my @NS_Parts = split(/::/, $NS);
7815 next if($#NS_Parts==-1);
7816 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7817 foreach my $NS_Part (@NS_Parts)
7818 {
7819 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7820 $TypeDecl_Suffix .= "}";
7821 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007822 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007823 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7824 $Additions.=" $TypeDecl\n $FuncDecl\n";
7825 $AddNameSpaceId+=1;
7826 }
7827 return $Additions;
7828}
7829
7830sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007831{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007832 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007833 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007834 if($Fmt eq "windows")
7835 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007836 $Path=~s/\//\\/g;
7837 $Path=lc($Path);
7838 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007839 else
7840 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007841 $Path=~s/\\/\//g;
7842 }
7843 return $Path;
7844}
7845
7846sub inc_opt($$)
7847{
7848 my ($Path, $Style) = @_;
7849 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007850 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007851 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007852 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007853 return "-I\"".path_format($Path, "unix")."\"";
7854 }
7855 elsif($OSgroup eq "macos"
7856 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007857 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007858 return "-F".esc(get_dirname($Path));
7859 }
7860 else {
7861 return "-I".esc($Path);
7862 }
7863 }
7864 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007865 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007866 }
7867 return "";
7868}
7869
7870sub platformSpecs($)
7871{
7872 my $LibVersion = $_[0];
7873 my $Arch = getArch($LibVersion);
7874 if($OStarget eq "symbian")
7875 { # options for GCCE compiler
7876 my %Symbian_Opts = map {$_=>1} (
7877 "-D__GCCE__",
7878 "-DUNICODE",
7879 "-fexceptions",
7880 "-D__SYMBIAN32__",
7881 "-D__MARM_INTERWORK__",
7882 "-D_UNICODE",
7883 "-D__S60_50__",
7884 "-D__S60_3X__",
7885 "-D__SERIES60_3X__",
7886 "-D__EPOC32__",
7887 "-D__MARM__",
7888 "-D__EABI__",
7889 "-D__MARM_ARMV5__",
7890 "-D__SUPPORT_CPP_EXCEPTIONS__",
7891 "-march=armv5t",
7892 "-mapcs",
7893 "-mthumb-interwork",
7894 "-DEKA2",
7895 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7896 );
7897 return join(" ", keys(%Symbian_Opts));
7898 }
7899 elsif($OSgroup eq "windows"
7900 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7901 { # add options to MinGW compiler
7902 # to simulate the MSVC compiler
7903 my %MinGW_Opts = map {$_=>1} (
7904 "-D_WIN32",
7905 "-D_STDCALL_SUPPORTED",
7906 "-D__int64=\"long long\"",
7907 "-D__int32=int",
7908 "-D__int16=short",
7909 "-D__int8=char",
7910 "-D__possibly_notnullterminated=\" \"",
7911 "-D__nullterminated=\" \"",
7912 "-D__nullnullterminated=\" \"",
7913 "-D__w64=\" \"",
7914 "-D__ptr32=\" \"",
7915 "-D__ptr64=\" \"",
7916 "-D__forceinline=inline",
7917 "-D__inline=inline",
7918 "-D__uuidof(x)=IID()",
7919 "-D__try=",
7920 "-D__except(x)=",
7921 "-D__declspec(x)=__attribute__((x))",
7922 "-D__pragma(x)=",
7923 "-D_inline=inline",
7924 "-D__forceinline=__inline",
7925 "-D__stdcall=__attribute__((__stdcall__))",
7926 "-D__cdecl=__attribute__((__cdecl__))",
7927 "-D__fastcall=__attribute__((__fastcall__))",
7928 "-D__thiscall=__attribute__((__thiscall__))",
7929 "-D_stdcall=__attribute__((__stdcall__))",
7930 "-D_cdecl=__attribute__((__cdecl__))",
7931 "-D_fastcall=__attribute__((__fastcall__))",
7932 "-D_thiscall=__attribute__((__thiscall__))",
7933 "-DSHSTDAPI_(x)=x",
7934 "-D_MSC_EXTENSIONS",
7935 "-DSECURITY_WIN32",
7936 "-D_MSC_VER=1500",
7937 "-D_USE_DECLSPECS_FOR_SAL",
7938 "-D__noop=\" \"",
7939 "-DDECLSPEC_DEPRECATED=\" \"",
7940 "-D__builtin_alignof(x)=__alignof__(x)",
7941 "-DSORTPP_PASS");
7942 if($Arch eq "x86") {
7943 $MinGW_Opts{"-D_M_IX86=300"}=1;
7944 }
7945 elsif($Arch eq "x86_64") {
7946 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7947 }
7948 elsif($Arch eq "ia64") {
7949 $MinGW_Opts{"-D_M_IA64=300"}=1;
7950 }
7951 return join(" ", keys(%MinGW_Opts));
7952 }
7953 return "";
7954}
7955
7956my %C_Structure = map {$_=>1} (
7957# FIXME: Can't separate union and struct data types before dumping,
7958# so it sometimes cause compilation errors for unknown reason
7959# when trying to declare TYPE* tmp_add_class_N
7960# This is a list of such structures + list of other C structures
7961 "sigval",
7962 "sigevent",
7963 "sigaction",
7964 "sigvec",
7965 "sigstack",
7966 "timeval",
7967 "timezone",
7968 "rusage",
7969 "rlimit",
7970 "wait",
7971 "flock",
7972 "stat",
7973 "_stat",
7974 "stat32",
7975 "_stat32",
7976 "stat64",
7977 "_stat64",
7978 "_stati64",
7979 "if_nameindex",
7980 "usb_device",
7981 "sigaltstack",
7982 "sysinfo",
7983 "timeLocale",
7984 "tcp_debug",
7985 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007986 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007987 "timespec",
7988 "random_data",
7989 "drand48_data",
7990 "_IO_marker",
7991 "_IO_FILE",
7992 "lconv",
7993 "sched_param",
7994 "tm",
7995 "itimerspec",
7996 "_pthread_cleanup_buffer",
7997 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007998 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007999 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008000 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008001 "sigcontext",
8002 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008003 # Mac
8004 "_timex",
8005 "_class_t",
8006 "_category_t",
8007 "_class_ro_t",
8008 "_protocol_t",
8009 "_message_ref_t",
8010 "_super_message_ref_t",
8011 "_ivar_t",
8012 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008013);
8014
8015sub getCompileCmd($$$)
8016{
8017 my ($Path, $Opt, $Inc) = @_;
8018 my $GccCall = $GCC_PATH;
8019 if($Opt) {
8020 $GccCall .= " ".$Opt;
8021 }
8022 $GccCall .= " -x ";
8023 if($OSgroup eq "macos") {
8024 $GccCall .= "objective-";
8025 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008026
8027 if($EMERGENCY_MODE_48)
8028 { # workaround for GCC 4.8 (C only)
8029 $GccCall .= "c++";
8030 }
8031 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008032 { # compile as "C++" header
8033 # to obtain complete dump using GCC 4.0
8034 $GccCall .= "c++-header";
8035 }
8036 else
8037 { # compile as "C++" source
8038 # GCC 3.3 cannot compile headers
8039 $GccCall .= "c++";
8040 }
8041 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008042 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008043 $GccCall .= " ".$Opts;
8044 }
8045 # allow extra qualifications
8046 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008047 $GccCall .= " -fpermissive";
8048 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008049 if($NoStdInc)
8050 {
8051 $GccCall .= " -nostdinc";
8052 $GccCall .= " -nostdinc++";
8053 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008054 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008055 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008056 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008057 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008058 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008059 if($Inc)
8060 { # include paths
8061 $GccCall .= " ".$Inc;
8062 }
8063 return $GccCall;
8064}
8065
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008066sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008067{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008068 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008069 my %HeaderElems = (
8070 # Types
8071 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008072 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008073 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8074 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008075 "time.h" => ["time_t"],
8076 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008077 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8078 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008079 "stdbool.h" => ["_Bool"],
8080 "rpc/xdr.h" => ["bool_t"],
8081 "in_systm.h" => ["n_long", "n_short"],
8082 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008083 "arpa/inet.h" => ["fw_src", "ip_src"],
8084 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008085 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008086 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008087 );
8088 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008089 foreach (keys(%HeaderElems))
8090 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008091 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008092 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008093 }
8094 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008095 my %Types = ();
8096 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8097 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008098 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008099 }
8100 if(keys(%Types))
8101 {
8102 my %AddHeaders = ();
8103 foreach my $Type (keys(%Types))
8104 {
8105 if(my $Header = $AutoPreamble{$Type})
8106 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008107 if(my $Path = identifyHeader($Header, $LibVersion))
8108 {
8109 if(skipHeader($Path, $LibVersion)) {
8110 next;
8111 }
8112 $Path = path_format($Path, $OSgroup);
8113 $AddHeaders{$Path}{"Type"} = $Type;
8114 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008115 }
8116 }
8117 }
8118 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008119 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008120 }
8121 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008122 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008123}
8124
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008125sub checkCTags($)
8126{
8127 my $Path = $_[0];
8128 if(not $Path) {
8129 return;
8130 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008131 my $CTags = undef;
8132
8133 if($OSgroup eq "bsd")
8134 { # use ectags on BSD
8135 $CTags = get_CmdPath("ectags");
8136 if(not $CTags) {
8137 printMsg("WARNING", "can't find \'ectags\' program");
8138 }
8139 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008140 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008141 $CTags = get_CmdPath("ctags");
8142 }
8143 if(not $CTags)
8144 {
8145 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008146 return;
8147 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008148
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008149 if($OSgroup ne "linux")
8150 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008151 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8152 if($Info!~/exuberant/i)
8153 {
8154 printMsg("WARNING", "incompatible version of \'ctags\' program");
8155 return;
8156 }
8157 }
8158
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008159 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008160 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008161 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008162 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008163 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008164 open(CTAGS, "<", $Out);
8165 while(my $Line = <CTAGS>)
8166 {
8167 chomp($Line);
8168 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008169 if(defined $Intrinsic_Keywords{$Name})
8170 { # noise
8171 next;
8172 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008173 if($Type eq "n")
8174 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008175 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008176 next;
8177 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008178 if(index($Scpe, "struct:")==0) {
8179 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008180 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008181 if(index($Scpe, "namespace:")==0)
8182 {
8183 if($Scpe=~s/\Anamespace://) {
8184 $Name = $Scpe."::".$Name;
8185 }
8186 }
8187 $TUnit_NameSpaces{$Version}{$Name} = 1;
8188 }
8189 elsif($Type eq "p")
8190 {
8191 if(not $Scpe or index($Scpe, "namespace:")==0) {
8192 $TUnit_Funcs{$Version}{$Name} = 1;
8193 }
8194 }
8195 elsif($Type eq "x")
8196 {
8197 if(not $Scpe or index($Scpe, "namespace:")==0) {
8198 $TUnit_Vars{$Version}{$Name} = 1;
8199 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008200 }
8201 }
8202 close(CTAGS);
8203}
8204
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008205sub preChange($$)
8206{
8207 my ($HeaderPath, $IncStr) = @_;
8208
8209 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8210 my $Content = undef;
8211
8212 if($OStarget eq "windows"
8213 and get_dumpmachine($GCC_PATH)=~/mingw/i
8214 and $MinGWMode{$Version}!=-1)
8215 { # modify headers to compile by MinGW
8216 if(not $Content)
8217 { # preprocessing
8218 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8219 }
8220 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8221 { # __asm { ... }
8222 $MinGWMode{$Version}=1;
8223 }
8224 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8225 { # comments after preprocessing
8226 $MinGWMode{$Version}=1;
8227 }
8228 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8229 { # 0xffui8
8230 $MinGWMode{$Version}=1;
8231 }
8232
8233 if($MinGWMode{$Version}) {
8234 printMsg("INFO", "Using MinGW compatibility mode");
8235 }
8236 }
8237
8238 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8239 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8240 { # rename C++ keywords in C code
8241 # disable this code by -cpp-compatible option
8242 if(not $Content)
8243 { # preprocessing
8244 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8245 }
8246 my $RegExp_C = join("|", keys(%CppKeywords_C));
8247 my $RegExp_F = join("|", keys(%CppKeywords_F));
8248 my $RegExp_O = join("|", keys(%CppKeywords_O));
8249
8250 my $Detected = undef;
8251
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008252 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 +04008253 { # MATCH:
8254 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008255 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008256 # unsigned private: 8;
8257 # DO NOT MATCH:
8258 # #pragma GCC visibility push(default)
8259 $CppMode{$Version} = 1;
8260 $Detected = "$1$2$3$4" if(not defined $Detected);
8261 }
8262 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8263 { # MATCH:
8264 # int delete(...);
8265 # int explicit(...);
8266 # DO NOT MATCH:
8267 # void operator delete(...)
8268 $CppMode{$Version} = 1;
8269 $Detected = "$1$2$3" if(not defined $Detected);
8270 }
8271 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8272 { # MATCH:
8273 # int bool;
8274 # DO NOT MATCH:
8275 # bool X;
8276 # return *this;
8277 # throw;
8278 $CppMode{$Version} = 1;
8279 $Detected = "$1$2$3" if(not defined $Detected);
8280 }
8281 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8282 { # MATCH:
8283 # int operator(...);
8284 # DO NOT MATCH:
8285 # int operator()(...);
8286 $CppMode{$Version} = 1;
8287 $Detected = "$1$2$3" if(not defined $Detected);
8288 }
8289 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8290 { # MATCH:
8291 # int foo(int operator);
8292 # int foo(int operator, int other);
8293 # DO NOT MATCH:
8294 # int operator,(...);
8295 $CppMode{$Version} = 1;
8296 $Detected = "$1$2$3" if(not defined $Detected);
8297 }
8298 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8299 { # MATCH:
8300 # int foo(gboolean *bool);
8301 # DO NOT MATCH:
8302 # void setTabEnabled(int index, bool);
8303 $CppMode{$Version} = 1;
8304 $Detected = "$1$2$3" if(not defined $Detected);
8305 }
8306 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8307 { # MATCH:
8308 # int foo(int* this);
8309 # int bar(int this);
8310 # int baz(int throw);
8311 # DO NOT MATCH:
8312 # foo(X, this);
8313 $CppMode{$Version} = 1;
8314 $Detected = "$1$2$3$4" if(not defined $Detected);
8315 }
8316 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8317 { # MATCH:
8318 # struct template {...};
8319 # extern template foo(...);
8320 $CppMode{$Version} = 1;
8321 $Detected = "$1$2" if(not defined $Detected);
8322 }
8323
8324 if($CppMode{$Version} == 1)
8325 {
8326 if($Debug)
8327 {
8328 $Detected=~s/\A\s+//g;
8329 printMsg("INFO", "Detected code: \"$Detected\"");
8330 }
8331 }
8332
8333 # remove typedef enum NAME NAME;
8334 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8335 my $N = 0;
8336 while($N<=$#FwdTypedefs-1)
8337 {
8338 my $S = $FwdTypedefs[$N];
8339 if($S eq $FwdTypedefs[$N+1])
8340 {
8341 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008342 $CppMode{$Version} = 1;
8343
8344 if($Debug) {
8345 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8346 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008347 }
8348 $N+=2;
8349 }
8350
8351 if($CppMode{$Version}==1) {
8352 printMsg("INFO", "Using C++ compatibility mode");
8353 }
8354 }
8355
8356 if($CppMode{$Version}==1
8357 or $MinGWMode{$Version}==1)
8358 {
8359 my $IPath = $TMP_DIR."/dump$Version.i";
8360 writeFile($IPath, $Content);
8361 return $IPath;
8362 }
8363
8364 return undef;
8365}
8366
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008367sub getDump()
8368{
8369 if(not $GCC_PATH) {
8370 exitStatus("Error", "internal error - GCC path is not set");
8371 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008372
8373 my @Headers = keys(%{$Registered_Headers{$Version}});
8374 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8375
8376 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8377
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008378 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008379 my $HeaderPath = $TmpHeaderPath;
8380
8381 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008382 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008383 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8384 {
8385 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008386 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008387 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008388 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008389 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8390 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008391 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008392 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008393 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008394 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8395 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008397 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008398 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008399
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008400 if($ExtraInfo)
8401 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008402 if($IncludeString) {
8403 writeFile($ExtraInfo."/include-string", $IncludeString);
8404 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008405 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8406 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008407
8408 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8409 {
8410 my $REDIR = "";
8411 foreach my $P1 (sort @Redirects) {
8412 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8413 }
8414 writeFile($ExtraInfo."/include-redirect", $REDIR);
8415 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008416 }
8417
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008418 if(not keys(%{$TargetHeaders{$Version}}))
8419 { # Target headers
8420 addTargetHeaders($Version);
8421 }
8422
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008423 # clean memory
8424 %RecursiveIncludes = ();
8425 %Header_Include_Prefix = ();
8426 %Header_Includes = ();
8427
8428 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008429 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008430 delete($Cache{"detect_header_includes"});
8431 delete($Cache{"selectSystemHeader"});
8432
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008434 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8435 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008436
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008437 if($ExtraInfo)
8438 { # extra information for other tools
8439 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8440 }
8441
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008442 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008443 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008444 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008445
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008446 if($COMMON_LANGUAGE{$Version} eq "C++") {
8447 checkCTags($Pre);
8448 }
8449
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008450 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8451 { # try to correct the preprocessor output
8452 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008453 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008454
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008455 if($COMMON_LANGUAGE{$Version} eq "C++")
8456 { # add classes and namespaces to the dump
8457 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008458 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008459 or $MinGWMode{$Version}==1) {
8460 $CHdump .= " -fpreprocessed";
8461 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008462 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008463 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008464 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008465 chdir($ORIG_DIR);
8466 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8467 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008468 my $Content = readFile($ClassDump);
8469 foreach my $ClassInfo (split(/\n\n/, $Content))
8470 {
8471 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8472 {
8473 my $CName = $1;
8474 next if($CName=~/\A(__|_objc_|_opaque_)/);
8475 $TUnit_NameSpaces{$Version}{$CName} = -1;
8476 if($CName=~/\A[\w:]+\Z/)
8477 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008478 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008479 }
8480 if($CName=~/(\w[\w:]*)::/)
8481 { # namespaces
8482 my $NS = $1;
8483 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8484 $TUnit_NameSpaces{$Version}{$NS} = 1;
8485 }
8486 }
8487 }
8488 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8489 { # read v-tables (advanced approach)
8490 my ($CName, $VTable) = ($1, $2);
8491 $ClassVTable_Content{$Version}{$CName} = $VTable;
8492 }
8493 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008494 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8495 { # add user-defined namespaces
8496 $TUnit_NameSpaces{$Version}{$NS} = 1;
8497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008498 if($Debug)
8499 { # debug mode
8500 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008501 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008502 }
8503 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008504 }
8505
8506 # add namespaces and classes
8507 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8508 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008509 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008510 }
8511 # some GCC versions don't include class methods to the TU dump by default
8512 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008513 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008514 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8515 {
8516 next if($C_Structure{$CName});
8517 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008518 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008519 if(not $Force and $GCC_44
8520 and $OSgroup eq "linux")
8521 { # optimization for linux with GCC >= 4.4
8522 # disable this code by -force option
8523 if(index($CName, "::")!=-1)
8524 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008525 next;
8526 }
8527 }
8528 else
8529 {
8530 if($CName=~/\A(.+)::[^:]+\Z/
8531 and $TUnit_Classes{$Version}{$1})
8532 { # classes inside other classes
8533 next;
8534 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008535 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008536 if(defined $TUnit_Funcs{$Version}{$CName})
8537 { # the same name for a function and type
8538 next;
8539 }
8540 if(defined $TUnit_Vars{$Version}{$CName})
8541 { # the same name for a variable and type
8542 next;
8543 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008544 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8545 }
8546 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008547 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008548 }
8549 }
8550 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8551 # create TU dump
8552 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008553 if($UserLang eq "C") {
8554 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8555 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008556 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008557 or $MinGWMode{$Version}==1) {
8558 $TUdump .= " -fpreprocessed";
8559 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008560 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008561 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8562 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008563 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008564 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008565 if($?)
8566 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008567 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008568 { # try to recompile
8569 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008570 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008571 and index($Errors, "c99_")!=-1
8572 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008573 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008574 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008575
8576 if($Debug)
8577 {
8578 # printMsg("INFO", $Errors);
8579 }
8580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008581 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008582 resetLogging($Version);
8583 $TMP_DIR = tempdir(CLEANUP=>1);
8584 return getDump();
8585 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008586 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008587 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008588 { # add auto preamble headers and try again
8589 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008590 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008591 foreach my $Num (0 .. $#Headers)
8592 {
8593 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008594 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8595 {
8596 push_U($Include_Preamble{$Version}, $Path);
8597 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008598 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008599 }
8600 resetLogging($Version);
8601 $TMP_DIR = tempdir(CLEANUP=>1);
8602 return getDump();
8603 }
8604 elsif($Cpp0xMode{$Version}!=-1
8605 and ($Errors=~/\Q-std=c++0x\E/
8606 or $Errors=~/is not a class or namespace/))
8607 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008608 if(check_gcc($GCC_PATH, "4.6"))
8609 {
8610 $Cpp0xMode{$Version}=-1;
8611 printMsg("INFO", "Enabling c++0x mode");
8612 resetLogging($Version);
8613 $TMP_DIR = tempdir(CLEANUP=>1);
8614 $CompilerOptions{$Version} .= " -std=c++0x";
8615 return getDump();
8616 }
8617 else {
8618 printMsg("WARNING", "Probably c++0x construction detected");
8619 }
8620
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008621 }
8622 elsif($MinGWMode{$Version}==1)
8623 { # disable MinGW mode and try again
8624 $MinGWMode{$Version}=-1;
8625 resetLogging($Version);
8626 $TMP_DIR = tempdir(CLEANUP=>1);
8627 return getDump();
8628 }
8629 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008630 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008631 else {
8632 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008634 printMsg("ERROR", "some errors occurred when compiling headers");
8635 printErrorLog($Version);
8636 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008637 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008638 }
8639 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008640 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008641 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008642
8643 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8644 return $TUs[0];
8645 }
8646 else
8647 {
8648 my $Msg = "can't compile header(s)";
8649 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8650 $Msg .= "\nDid you install G++?";
8651 }
8652 exitStatus("Cannot_Compile", $Msg);
8653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008654}
8655
8656sub cmd_file($)
8657{
8658 my $Path = $_[0];
8659 return "" if(not $Path or not -e $Path);
8660 if(my $CmdPath = get_CmdPath("file")) {
8661 return `$CmdPath -b \"$Path\"`;
8662 }
8663 return "";
8664}
8665
8666sub getIncString($$)
8667{
8668 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008669 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008670 my $String = "";
8671 foreach (@{$ArrRef}) {
8672 $String .= " ".inc_opt($_, $Style);
8673 }
8674 return $String;
8675}
8676
8677sub getIncPaths(@)
8678{
8679 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008680 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008681 if($INC_PATH_AUTODETECT{$Version})
8682 { # auto-detecting dependencies
8683 my %Includes = ();
8684 foreach my $HPath (@HeaderPaths)
8685 {
8686 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8687 {
8688 if($Skip_Include_Paths{$Version}{$Dir}) {
8689 next;
8690 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008691 if($SystemRoot)
8692 {
8693 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8694 next;
8695 }
8696 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008697 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008698 }
8699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008700 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008701 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008702 }
8703 }
8704 else
8705 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008706 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008707 }
8708 return \@IncPaths;
8709}
8710
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008711sub push_U($@)
8712{ # push unique
8713 if(my $Array = shift @_)
8714 {
8715 if(@_)
8716 {
8717 my %Exist = map {$_=>1} @{$Array};
8718 foreach my $Elem (@_)
8719 {
8720 if(not defined $Exist{$Elem})
8721 {
8722 push(@{$Array}, $Elem);
8723 $Exist{$Elem} = 1;
8724 }
8725 }
8726 }
8727 }
8728}
8729
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008730sub callPreprocessor($$$)
8731{
8732 my ($Path, $Inc, $LibVersion) = @_;
8733 return "" if(not $Path or not -f $Path);
8734 my $IncludeString=$Inc;
8735 if(not $Inc) {
8736 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8737 }
8738 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008739 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008740 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008741 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008742}
8743
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008744sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008745{ # native "find" is much faster than File::Find (~6x)
8746 # also the File::Find doesn't support --maxdepth N option
8747 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008748 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008749 return () if(not $Path or not -e $Path);
8750 if($OSgroup eq "windows")
8751 {
8752 my $DirCmd = get_CmdPath("dir");
8753 if(not $DirCmd) {
8754 exitStatus("Not_Found", "can't find \"dir\" command");
8755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008756 $Path = get_abs_path($Path);
8757 $Path = path_format($Path, $OSgroup);
8758 my $Cmd = $DirCmd." \"$Path\" /B /O";
8759 if($MaxDepth!=1) {
8760 $Cmd .= " /S";
8761 }
8762 if($Type eq "d") {
8763 $Cmd .= " /AD";
8764 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008765 elsif($Type eq "f") {
8766 $Cmd .= " /A-D";
8767 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008768 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008769 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008770 {
8771 if(not $UseRegex)
8772 { # FIXME: how to search file names in MS shell?
8773 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008774 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008775 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008776 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008777 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008778 }
8779 my @AbsPaths = ();
8780 foreach my $File (@Files)
8781 {
8782 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008783 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784 }
8785 if($Type eq "f" and not -f $File)
8786 { # skip dirs
8787 next;
8788 }
8789 push(@AbsPaths, path_format($File, $OSgroup));
8790 }
8791 if($Type eq "d") {
8792 push(@AbsPaths, $Path);
8793 }
8794 return @AbsPaths;
8795 }
8796 else
8797 {
8798 my $FindCmd = get_CmdPath("find");
8799 if(not $FindCmd) {
8800 exitStatus("Not_Found", "can't find a \"find\" command");
8801 }
8802 $Path = get_abs_path($Path);
8803 if(-d $Path and -l $Path
8804 and $Path!~/\/\Z/)
8805 { # for directories that are symlinks
8806 $Path.="/";
8807 }
8808 my $Cmd = $FindCmd." \"$Path\"";
8809 if($MaxDepth) {
8810 $Cmd .= " -maxdepth $MaxDepth";
8811 }
8812 if($Type) {
8813 $Cmd .= " -type $Type";
8814 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008815 if($Name and not $UseRegex)
8816 { # wildcards
8817 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008819 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008820 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008821 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8822 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008823 my @Files = split(/\n/, $Res);
8824 if($Name and $UseRegex)
8825 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008826 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008827 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008828 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008829 }
8830}
8831
8832sub unpackDump($)
8833{
8834 my $Path = $_[0];
8835 return "" if(not $Path or not -e $Path);
8836 $Path = get_abs_path($Path);
8837 $Path = path_format($Path, $OSgroup);
8838 my ($Dir, $FileName) = separate_path($Path);
8839 my $UnpackDir = $TMP_DIR."/unpack";
8840 rmtree($UnpackDir);
8841 mkpath($UnpackDir);
8842 if($FileName=~s/\Q.zip\E\Z//g)
8843 { # *.zip
8844 my $UnzipCmd = get_CmdPath("unzip");
8845 if(not $UnzipCmd) {
8846 exitStatus("Not_Found", "can't find \"unzip\" command");
8847 }
8848 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008849 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008851 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 }
8853 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008854 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008855 if(not @Contents) {
8856 exitStatus("Error", "can't extract \'$Path\'");
8857 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008858 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008859 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008860 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008861 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008862 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008863 if($OSgroup eq "windows")
8864 { # -xvzf option is not implemented in tar.exe (2003)
8865 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8866 my $TarCmd = get_CmdPath("tar");
8867 if(not $TarCmd) {
8868 exitStatus("Not_Found", "can't find \"tar\" command");
8869 }
8870 my $GzipCmd = get_CmdPath("gzip");
8871 if(not $GzipCmd) {
8872 exitStatus("Not_Found", "can't find \"gzip\" command");
8873 }
8874 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008875 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008876 if($?) {
8877 exitStatus("Error", "can't extract \'$Path\'");
8878 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008879 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008880 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008881 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882 }
8883 chdir($ORIG_DIR);
8884 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008885 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008886 if(not @Contents) {
8887 exitStatus("Error", "can't extract \'$Path\'");
8888 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008889 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008890 }
8891 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008892 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008893 my $TarCmd = get_CmdPath("tar");
8894 if(not $TarCmd) {
8895 exitStatus("Not_Found", "can't find \"tar\" command");
8896 }
8897 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008898 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008899 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008900 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008901 }
8902 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008903 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008904 if(not @Contents) {
8905 exitStatus("Error", "can't extract \'$Path\'");
8906 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008907 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008908 }
8909 }
8910}
8911
8912sub createArchive($$)
8913{
8914 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008915 if(not $To) {
8916 $To = ".";
8917 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008918 if(not $Path or not -e $Path
8919 or not -d $To) {
8920 return "";
8921 }
8922 my ($From, $Name) = separate_path($Path);
8923 if($OSgroup eq "windows")
8924 { # *.zip
8925 my $ZipCmd = get_CmdPath("zip");
8926 if(not $ZipCmd) {
8927 exitStatus("Not_Found", "can't find \"zip\"");
8928 }
8929 my $Pkg = $To."/".$Name.".zip";
8930 unlink($Pkg);
8931 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008932 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008933 if($?)
8934 { # cannot allocate memory (or other problems with "zip")
8935 unlink($Path);
8936 exitStatus("Error", "can't pack the ABI dump: ".$!);
8937 }
8938 chdir($ORIG_DIR);
8939 unlink($Path);
8940 return $Pkg;
8941 }
8942 else
8943 { # *.tar.gz
8944 my $TarCmd = get_CmdPath("tar");
8945 if(not $TarCmd) {
8946 exitStatus("Not_Found", "can't find \"tar\"");
8947 }
8948 my $GzipCmd = get_CmdPath("gzip");
8949 if(not $GzipCmd) {
8950 exitStatus("Not_Found", "can't find \"gzip\"");
8951 }
8952 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8953 unlink($Pkg);
8954 chdir($From);
8955 system($TarCmd, "-czf", $Pkg, $Name);
8956 if($?)
8957 { # cannot allocate memory (or other problems with "tar")
8958 unlink($Path);
8959 exitStatus("Error", "can't pack the ABI dump: ".$!);
8960 }
8961 chdir($ORIG_DIR);
8962 unlink($Path);
8963 return $To."/".$Name.".tar.gz";
8964 }
8965}
8966
8967sub is_header_file($)
8968{
8969 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8970 return $_[0];
8971 }
8972 return 0;
8973}
8974
8975sub is_not_header($)
8976{
8977 if($_[0]=~/\.\w+\Z/
8978 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8979 return 1;
8980 }
8981 return 0;
8982}
8983
8984sub is_header($$$)
8985{
8986 my ($Header, $UserDefined, $LibVersion) = @_;
8987 return 0 if(-d $Header);
8988 if(-f $Header) {
8989 $Header = get_abs_path($Header);
8990 }
8991 else
8992 {
8993 if(is_abs($Header))
8994 { # incorrect absolute path
8995 return 0;
8996 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008997 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008998 $Header = $HPath;
8999 }
9000 else
9001 { # can't find header
9002 return 0;
9003 }
9004 }
9005 if($Header=~/\.\w+\Z/)
9006 { # have an extension
9007 return is_header_file($Header);
9008 }
9009 else
9010 {
9011 if($UserDefined==2)
9012 { # specified on the command line
9013 if(cmd_file($Header)!~/HTML|XML/i) {
9014 return $Header;
9015 }
9016 }
9017 elsif($UserDefined)
9018 { # specified in the XML-descriptor
9019 # header file without an extension
9020 return $Header;
9021 }
9022 else
9023 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009024 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009025 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009026 { # !~/HTML|XML|shared|dynamic/i
9027 return $Header;
9028 }
9029 }
9030 }
9031 return 0;
9032}
9033
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009034sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009035{
9036 my $LibVersion = $_[0];
9037 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9038 {
9039 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009040 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009041
9042 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9043 detect_recursive_includes($RegHeader, $LibVersion);
9044 }
9045
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009046 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9047 {
9048 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009049
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009050 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009051 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9052 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009053 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009054 }
9055 }
9056 }
9057}
9058
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009059sub familiarDirs($$)
9060{
9061 my ($D1, $D2) = @_;
9062 if($D1 eq $D2) {
9063 return 1;
9064 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009065
9066 my $U1 = index($D1, "/usr/");
9067 my $U2 = index($D2, "/usr/");
9068
9069 if($U1==0 and $U2!=0) {
9070 return 0;
9071 }
9072
9073 if($U2==0 and $U1!=0) {
9074 return 0;
9075 }
9076
9077 if(index($D2, $D1."/")==0) {
9078 return 1;
9079 }
9080
9081 # /usr/include/DIR
9082 # /home/user/DIR
9083
9084 my $DL = get_depth($D1);
9085
9086 my @Dirs1 = ($D1);
9087 while($DL - get_depth($D1)<=2
9088 and get_depth($D1)>=4
9089 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9090 push(@Dirs1, $D1);
9091 }
9092
9093 my @Dirs2 = ($D2);
9094 while(get_depth($D2)>=4
9095 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9096 push(@Dirs2, $D2);
9097 }
9098
9099 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009100 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009101 foreach my $P2 (@Dirs2)
9102 {
9103
9104 if($P1 eq $P2) {
9105 return 1;
9106 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009107 }
9108 }
9109 return 0;
9110}
9111
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009112sub readHeaders($)
9113{
9114 $Version = $_[0];
9115 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9116 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009117 if($Debug)
9118 { # debug mode
9119 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009120 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009121 }
9122 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009123}
9124
9125sub prepareTypes($)
9126{
9127 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009128 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009129 { # support for old ABI dumps
9130 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009131 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009132 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009133 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9134 if($TName=~/\A(\w+)::(\w+)/) {
9135 my ($P1, $P2) = ($1, $2);
9136 if($P1 eq $P2) {
9137 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009139 else {
9140 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009142 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009143 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009144 }
9145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009146 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009147 { # support for old ABI dumps
9148 # V < 2.5: array size == "number of elements"
9149 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009150 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009151 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009152 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009153 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009155 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009156 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009157 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009158 $Size *= $Base{"Size"};
9159 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009160 }
9161 else
9162 { # array[] is a pointer
9163 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009164 }
9165 }
9166 }
9167 }
9168 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009169 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009170 { # support for old ABI dumps
9171 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009172 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009173 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009174 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009175 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009176 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009177 my %Type = get_Type($TypeId, $LibVersion);
9178 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9179 my %Type2 = get_Type($TypeId_2, $V2);
9180 if($Type{"Size"} ne $Type2{"Size"}) {
9181 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009182 }
9183 }
9184 }
9185 }
9186}
9187
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009188sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009189{
9190 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009191
9192 if(not keys(%{$SymbolInfo{$LibVersion}}))
9193 { # check if input is valid
9194 if(not $ExtendedCheck and not $CheckObjectsOnly)
9195 {
9196 if($CheckHeadersOnly) {
9197 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9198 }
9199 else {
9200 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9201 }
9202 }
9203 }
9204
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009205 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009206 if(not checkDump(1, "2.10")
9207 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009208 { # different formats
9209 $Remangle = 1;
9210 }
9211 if($CheckHeadersOnly)
9212 { # different languages
9213 if($UserLang)
9214 { # --lang=LANG for both versions
9215 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9216 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9217 {
9218 if($UserLang eq "C++")
9219 { # remangle symbols
9220 $Remangle = 1;
9221 }
9222 elsif($UserLang eq "C")
9223 { # remove mangling
9224 $Remangle = -1;
9225 }
9226 }
9227 }
9228 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009229
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009230 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009231 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009232 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009233 { # support for old ABI dumps
9234 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9235 {
9236 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9237 {
9238 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9239 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009240 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009241 if(defined $DVal and $DVal ne "")
9242 {
9243 if($TName eq "char") {
9244 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9245 }
9246 elsif($TName eq "bool") {
9247 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9248 }
9249 }
9250 }
9251 }
9252 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009253 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009254 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009255 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9256 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009257 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009258 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9259 # + support for old ABI dumps
9260 next;
9261 }
9262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009263 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009264 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009265 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009266 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009267
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009268 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009269 if(not checkDump(1, "2.12")
9270 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009271 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009272 if($ShortName eq "operator>>")
9273 {
9274 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9275 { # corrected mangling of operator>>
9276 $SRemangle = 1;
9277 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009278 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009279 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9280 {
9281 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9282 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9283 { # corrected mangling of const global data
9284 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9285 # and incorrectly mangled by old ACC versions
9286 $SRemangle = 1;
9287 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009288 }
9289 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009290 if(not $CheckHeadersOnly)
9291 { # support for old ABI dumps
9292 if(not checkDump(1, "2.17")
9293 or not checkDump(2, "2.17"))
9294 {
9295 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9296 {
9297 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9298 {
9299 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9300 {
9301 $MnglName = $ShortName;
9302 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9303 }
9304 }
9305 }
9306 }
9307 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009308 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009309 { # support for old ABI dumps: some symbols are not mangled in old dumps
9310 # mangle both sets of symbols (old and new)
9311 # NOTE: remangling all symbols by the same mangler
9312 if($MnglName=~/\A_ZN(V|)K/)
9313 { # mangling may be incorrect on old ABI dumps
9314 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009315 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009316 }
9317 if($MnglName=~/\A_ZN(K|)V/)
9318 { # mangling may be incorrect on old ABI dumps
9319 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009320 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009322 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9323 or (not $ClassID and $CheckHeadersOnly)
9324 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9325 { # support for old ABI dumps, GCC >= 4.0
9326 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009327 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009328 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009329 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009330 $MangledNames{$LibVersion}{$MnglName} = 1;
9331 }
9332 }
9333 }
9334 elsif($Remangle==-1)
9335 { # remove mangling
9336 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009337 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009339 if(not $MnglName) {
9340 next;
9341 }
9342 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9343 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009344 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009347 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009348 { # support for old dumps
9349 # add "Volatile" attribute
9350 if($MnglName=~/_Z(K|)V/) {
9351 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9352 }
9353 }
9354 # symbol and its symlink have same signatures
9355 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009356 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009357 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009358
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009359 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9360 {
9361 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9362 if($SymVer{$LibVersion}{$Alias}) {
9363 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9364 }
9365 }
9366
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009367 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009368 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009369 }
9370 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9371 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9372 }
9373 if($ExtendedCheck)
9374 { # --ext option
9375 addExtension($LibVersion);
9376 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009377
9378 # clean memory
9379 delete($SymbolInfo{$LibVersion});
9380
9381 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009382 { # detect allocable classes with public exported constructors
9383 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009384 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009385 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009387 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009388 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9389 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009390 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009391 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009393 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 $AllocableClass{$LibVersion}{$ClassName} = 1;
9395 }
9396 }
9397 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009398 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009400 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009401 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009402 if($CheckHeadersOnly)
9403 {
9404 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9405 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9406 { # all symbols except non-virtual inline
9407 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9408 }
9409 }
9410 else {
9411 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009412 }
9413 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009414 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009415 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 }
9417 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009418 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009419 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009420 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009422 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009423 if(defined $Base{"Type"}
9424 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009425 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009426 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009427 if($Name=~/<([^<>\s]+)>/)
9428 {
9429 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9430 $ReturnedClass{$LibVersion}{$Tid} = 1;
9431 }
9432 }
9433 else {
9434 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9435 }
9436 }
9437 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009438 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009439 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009440 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009441 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009442 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009443 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009444 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009445 if($Base{"Type"}=~/Struct|Class/)
9446 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009447 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009448 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9449 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009450 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 }
9453 }
9454 }
9455 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009456
9457 # mapping {short name => symbols}
9458 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009460 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009461 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009462 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009464 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009465 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009466 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9467 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009468 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009469 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 }
9471 }
9472 }
9473 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009474
9475 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009476 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009477 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009478 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009479 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009480 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9481 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009482 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009483 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009484 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009485 $ClassNames{$LibVersion}{$TName} = 1;
9486 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009487 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009488 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9489 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 }
9491 }
9492 }
9493 }
9494 }
9495}
9496
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009497sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009498{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009499 my ($Tid, $LibVersion) = @_;
9500 if(not $Tid) {
9501 return $Tid;
9502 }
9503
9504 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9505 {
9506 if($TName_Tid{$LibVersion}{$Name}) {
9507 return $TName_Tid{$LibVersion}{$Name};
9508 }
9509 }
9510
9511 return $Tid;
9512}
9513
9514sub register_SymbolUsage($$$)
9515{
9516 my ($InfoId, $UsedType, $LibVersion) = @_;
9517
9518 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9519 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9520 {
9521 register_TypeUsage($RTid, $UsedType, $LibVersion);
9522 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9523 }
9524 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9525 {
9526 register_TypeUsage($FCid, $UsedType, $LibVersion);
9527 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9528
9529 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9530 { # register "this" pointer
9531 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9532 }
9533 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9534 { # register "this" pointer (const method)
9535 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9536 }
9537 }
9538 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9539 {
9540 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9541 {
9542 register_TypeUsage($PTid, $UsedType, $LibVersion);
9543 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9544 }
9545 }
9546 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9547 {
9548 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9549 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9550 register_TypeUsage($TTid, $UsedType, $LibVersion);
9551 }
9552 }
9553}
9554
9555sub register_TypeUsage($$$)
9556{
9557 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009558 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009559 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009560 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009561 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009562 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009563 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009564 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009565
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009566 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009567 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009568 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009569 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009570 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009571 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9572 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9573 }
9574 }
9575
9576 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9577 {
9578 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009579 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009580 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009581 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9582 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009583 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009584 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9585 {
9586 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9587 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009588 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009589 }
9590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009591 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009592 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009593 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009594 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9595 {
9596 register_TypeUsage($MTid, $UsedType, $LibVersion);
9597 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009598 }
9599 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009600 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009601 or $TInfo{"Type"} eq "MethodPtr"
9602 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009603 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009604 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009605 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009606 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009607 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009608 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009609 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9610 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009611 }
9612 }
9613 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009614 if($TInfo{"Type"} eq "FieldPtr")
9615 {
9616 if(my $RTid = $TInfo{"Return"}) {
9617 register_TypeUsage($RTid, $UsedType, $LibVersion);
9618 }
9619 if(my $CTid = $TInfo{"Class"}) {
9620 register_TypeUsage($CTid, $UsedType, $LibVersion);
9621 }
9622 }
9623 if($TInfo{"Type"} eq "MethodPtr")
9624 {
9625 if(my $CTid = $TInfo{"Class"}) {
9626 register_TypeUsage($CTid, $UsedType, $LibVersion);
9627 }
9628 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009630 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009631 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009632 $UsedType->{$TypeId} = 1;
9633 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9634 {
9635 register_TypeUsage($BTid, $UsedType, $LibVersion);
9636 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9637 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009638 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009639 else
9640 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9641 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009642 }
9643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009644}
9645
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009646sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009647{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009648 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9649
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009650 if($Level eq "Dump")
9651 {
9652 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9653 { # TODO: check if this symbol is from
9654 # base classes of other target symbols
9655 return 1;
9656 }
9657 }
9658
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009659 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9660 { # stdc++ interfaces
9661 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009662 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009663
9664 my $Target = 0;
9665 if(my $Header = $SInfo->{"Header"}) {
9666 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9667 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009668 if($ExtendedCheck)
9669 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009670 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009671 $Target = 1;
9672 }
9673 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009674 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009675 {
9676 if($Target)
9677 {
9678 if($Level eq "Dump")
9679 { # dumped
9680 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009681 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009682 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009683 return 1;
9684 }
9685 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009686 else {
9687 return 1;
9688 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009689 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009690 elsif($Level eq "Source")
9691 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009692 return 1;
9693 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009694 elsif($Level eq "Binary")
9695 { # checked
9696 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9697 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9698 return 1;
9699 }
9700 }
9701 }
9702 }
9703 else
9704 { # library is available
9705 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9706 { # exported symbols
9707 return 1;
9708 }
9709 if($Level eq "Dump")
9710 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009711 if($BinaryOnly)
9712 {
9713 if($SInfo->{"Data"})
9714 {
9715 if($Target) {
9716 return 1;
9717 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009718 }
9719 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009720 else
9721 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009722 if($Target) {
9723 return 1;
9724 }
9725 }
9726 }
9727 elsif($Level eq "Source")
9728 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009729 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9730 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009731 { # skip LOCAL symbols
9732 if($Target) {
9733 return 1;
9734 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009735 }
9736 }
9737 elsif($Level eq "Binary")
9738 { # checked
9739 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9740 {
9741 if($Target) {
9742 return 1;
9743 }
9744 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009745 }
9746 }
9747 return 0;
9748}
9749
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009750sub cleanDump($)
9751{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009752 my $LibVersion = $_[0];
9753 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9754 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009755 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9756 {
9757 delete($SymbolInfo{$LibVersion}{$InfoId});
9758 next;
9759 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009760 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009761 if(not $MnglName)
9762 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009763 delete($SymbolInfo{$LibVersion}{$InfoId});
9764 next;
9765 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009766 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009767 if(not $ShortName)
9768 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009769 delete($SymbolInfo{$LibVersion}{$InfoId});
9770 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009771 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009772 if($MnglName eq $ShortName)
9773 { # remove duplicate data
9774 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009775 }
9776 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9777 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9778 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009779 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9780 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9781 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009782 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009784 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009785 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009786 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9787 {
9788 delete($TypeInfo{$LibVersion}{$Tid});
9789 next;
9790 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009791 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009792 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009793 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009794 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9795 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9796 }
9797 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009798 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9799 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9800 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009801 }
9802}
9803
9804sub selectType($$)
9805{
9806 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009807
9808 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9809 {
9810 if(defined $TypeInfo{$LibVersion}{$Dupl})
9811 {
9812 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9813 { # duplicate
9814 return 0;
9815 }
9816 }
9817 }
9818
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009819 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9820 {
9821 if(not isBuiltIn($THeader))
9822 {
9823 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009824 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009825 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9826 {
9827 if(is_target_header($THeader, $LibVersion))
9828 { # from target headers
9829 if(not selfTypedef($Tid, $LibVersion)) {
9830 return 1;
9831 }
9832 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009833 }
9834 }
9835 }
9836 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009837 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009838}
9839
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009840sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009841{ # remove unused data types from the ABI dump
9842 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009843
9844 my %UsedType = ();
9845
9846 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009847 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009848 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009849 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009850 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009851 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009852 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009853 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009854 next;
9855 }
9856
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009857 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009858 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009859 if(selectType($Tid, $LibVersion))
9860 {
9861 my %Tree = ();
9862 register_TypeUsage($Tid, \%Tree, $LibVersion);
9863
9864 my $Tmpl = 0;
9865 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9866 {
9867 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9868 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9869 {
9870 $Tmpl = 1;
9871 last;
9872 }
9873 }
9874 if(not $Tmpl)
9875 {
9876 foreach (keys(%Tree)) {
9877 $UsedType{$_} = 1;
9878 }
9879 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009880 }
9881 }
9882 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009883
9884 my %Delete = ();
9885
9886 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009887 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009888 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009889 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009890 next;
9891 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009892
9893 if($Kind eq "Extra")
9894 {
9895 my %Tree = ();
9896 register_TypeUsage($Tid, \%Tree, $LibVersion);
9897
9898 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9899 {
9900 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9901 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9902 {
9903 $Delete{$Tid} = 1;
9904 last;
9905 }
9906 }
9907 }
9908 else
9909 {
9910 # remove type
9911 delete($TypeInfo{$LibVersion}{$Tid});
9912 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009913 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009914
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009915 if($Kind eq "Extra")
9916 { # remove duplicates
9917 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9918 {
9919 if($UsedType{$Tid})
9920 { # All & Extended
9921 next;
9922 }
9923
9924 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9925
9926 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9927 delete($TypeInfo{$LibVersion}{$Tid});
9928 }
9929 }
9930 }
9931
9932 foreach my $Tid (keys(%Delete))
9933 {
9934 delete($TypeInfo{$LibVersion}{$Tid});
9935 }
9936}
9937
9938sub check_Completeness($$)
9939{
9940 my ($Info, $LibVersion) = @_;
9941
9942 # data types
9943 if(defined $Info->{"Memb"})
9944 {
9945 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9946 {
9947 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9948 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9949 }
9950 }
9951 }
9952 if(defined $Info->{"Base"})
9953 {
9954 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9955 check_TypeInfo($Bid, $LibVersion);
9956 }
9957 }
9958 if(defined $Info->{"BaseType"}) {
9959 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9960 }
9961 if(defined $Info->{"TParam"})
9962 {
9963 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9964 {
9965 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9966 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9967 next;
9968 }
9969 if($TName eq "_BoolType") {
9970 next;
9971 }
9972 if($TName=~/\Asizeof\(/) {
9973 next;
9974 }
9975 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9976 check_TypeInfo($Tid, $LibVersion);
9977 }
9978 else
9979 {
9980 if(defined $Debug) {
9981 printMsg("WARNING", "missed type $TName");
9982 }
9983 }
9984 }
9985 }
9986
9987 # symbols
9988 if(defined $Info->{"Param"})
9989 {
9990 foreach my $Pos (keys(%{$Info->{"Param"}}))
9991 {
9992 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9993 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9994 }
9995 }
9996 }
9997 if(defined $Info->{"Return"}) {
9998 check_TypeInfo($Info->{"Return"}, $LibVersion);
9999 }
10000 if(defined $Info->{"Class"}) {
10001 check_TypeInfo($Info->{"Class"}, $LibVersion);
10002 }
10003}
10004
10005sub check_TypeInfo($$)
10006{
10007 my ($Tid, $LibVersion) = @_;
10008
10009 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10010 return;
10011 }
10012 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10013
10014 if(defined $TypeInfo{$LibVersion}{$Tid})
10015 {
10016 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10017 printMsg("ERROR", "missed type name ($Tid)");
10018 }
10019 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10020 }
10021 else {
10022 printMsg("ERROR", "missed type id $Tid");
10023 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010024}
10025
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010026sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010027{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010028 my ($TypeId, $LibVersion) = @_;
10029 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010030 if($Type{"Type"} eq "Typedef")
10031 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010032 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010033 if($Base{"Type"}=~/Class|Struct/)
10034 {
10035 if($Type{"Name"} eq $Base{"Name"}) {
10036 return 1;
10037 }
10038 elsif($Type{"Name"}=~/::(\w+)\Z/)
10039 {
10040 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10041 { # QPointer<QWidget>::QPointer
10042 return 1;
10043 }
10044 }
10045 }
10046 }
10047 return 0;
10048}
10049
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010050sub addExtension($)
10051{
10052 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010053 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010054 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010055 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010056 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010057 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10058 $TName=~s/\A(struct|union|class|enum) //;
10059 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010060
10061 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10062 "Header" => "extended.h",
10063 "ShortName" => $Symbol,
10064 "MnglName" => $Symbol,
10065 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10066 );
10067
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010068 $ExtendedSymbols{$Symbol} = 1;
10069 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10070 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010071 }
10072 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010073 $ExtendedSymbols{"external_func_0"} = 1;
10074 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10075 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010076}
10077
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010078sub findMethod($$$)
10079{
10080 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010081 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010082 {
10083 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10084 return $VirtMethodInClass;
10085 }
10086 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10087 return $VirtMethodInBaseClasses;
10088 }
10089 }
10090 return "";
10091}
10092
10093sub findMethod_Class($$$)
10094{
10095 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010096 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010097 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10098 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10099 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10100 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10101 { # search for interface with the same parameters suffix (overridden)
10102 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10103 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010104 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10105 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010106 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10107 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010108 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10109 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10110 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10111 return $Candidate;
10112 }
10113 }
10114 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010115 else
10116 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010117 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10118 return $Candidate;
10119 }
10120 }
10121 }
10122 }
10123 return "";
10124}
10125
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010126sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010127{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010128 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010129 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010130 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010131 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10132 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010133 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010134 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010135 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010136 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10137 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010138 { # pure virtual D2-destructors are marked as "virt" in the dump
10139 # virtual D2-destructors are NOT marked as "virt" in the dump
10140 # both destructors are not presented in the v-table
10141 next;
10142 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010143 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010144 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010146 }
10147}
10148
10149sub registerOverriding($)
10150{
10151 my $LibVersion = $_[0];
10152 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010153 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010154 foreach my $ClassName (@Classes)
10155 {
10156 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10157 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010158 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10159 { # pure virtuals
10160 next;
10161 }
10162 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10163 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010164 {
10165 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10166 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10167 { # both overridden virtual methods
10168 # and implemented pure virtual methods
10169 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10170 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10171 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010173 }
10174 }
10175 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10176 delete($VirtualTable{$LibVersion}{$ClassName});
10177 }
10178 }
10179}
10180
10181sub setVirtFuncPositions($)
10182{
10183 my $LibVersion = $_[0];
10184 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10185 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010186 my ($Num, $Rel) = (1, 0);
10187
10188 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010189 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010190 if($UsedDump{$LibVersion}{"DWARF"}) {
10191 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10192 }
10193 else {
10194 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10195 }
10196 foreach my $VirtFunc (@Funcs)
10197 {
10198 if($UsedDump{$LibVersion}{"DWARF"}) {
10199 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10200 }
10201 else {
10202 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10203 }
10204
10205 # set relative positions
10206 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10207 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10208 { # relative position excluding added and removed virtual functions
10209 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10210 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10211 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215 }
10216 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010217 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010218 {
10219 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010220 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010221 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010222 }
10223 }
10224}
10225
10226sub get_sub_classes($$$)
10227{
10228 my ($ClassId, $LibVersion, $Recursive) = @_;
10229 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10230 my @Subs = ();
10231 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10232 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010233 if($Recursive)
10234 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010235 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10236 push(@Subs, $SubSubId);
10237 }
10238 }
10239 push(@Subs, $SubId);
10240 }
10241 return @Subs;
10242}
10243
10244sub get_base_classes($$$)
10245{
10246 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010247 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010248 return () if(not defined $ClassType{"Base"});
10249 my @Bases = ();
10250 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10251 keys(%{$ClassType{"Base"}}))
10252 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010253 if($Recursive)
10254 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010255 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10256 push(@Bases, $SubBaseId);
10257 }
10258 }
10259 push(@Bases, $BaseId);
10260 }
10261 return @Bases;
10262}
10263
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010264sub getVTable_Model($$)
10265{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010266 my ($ClassId, $LibVersion) = @_;
10267 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10268 my @Elements = ();
10269 foreach my $BaseId (@Bases, $ClassId)
10270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010271 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010272 {
10273 if(defined $VirtualTable{$LibVersion}{$BName})
10274 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010275 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10276 if($UsedDump{$LibVersion}{"DWARF"}) {
10277 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10278 }
10279 else {
10280 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10281 }
10282 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010283 push(@Elements, $VFunc);
10284 }
10285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010286 }
10287 }
10288 return @Elements;
10289}
10290
10291sub getVShift($$)
10292{
10293 my ($ClassId, $LibVersion) = @_;
10294 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10295 my $VShift = 0;
10296 foreach my $BaseId (@Bases)
10297 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010298 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010299 {
10300 if(defined $VirtualTable{$LibVersion}{$BName}) {
10301 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010303 }
10304 }
10305 return $VShift;
10306}
10307
10308sub getShift($$)
10309{
10310 my ($ClassId, $LibVersion) = @_;
10311 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10312 my $Shift = 0;
10313 foreach my $BaseId (@Bases)
10314 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010315 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010316 {
10317 if($Size!=1)
10318 { # not empty base class
10319 $Shift+=$Size;
10320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010321 }
10322 }
10323 return $Shift;
10324}
10325
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010326sub getVTable_Size($$)
10327{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010328 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010329 my $Size = 0;
10330 # three approaches
10331 if(not $Size)
10332 { # real size
10333 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10334 $Size = keys(%VTable);
10335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010336 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010337 if(not $Size)
10338 { # shared library symbol size
10339 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10340 $Size /= $WORD_SIZE{$LibVersion};
10341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010343 if(not $Size)
10344 { # model size
10345 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10346 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10347 }
10348 }
10349 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010350}
10351
10352sub isCopyingClass($$)
10353{
10354 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010355 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010356}
10357
10358sub isLeafClass($$)
10359{
10360 my ($ClassId, $LibVersion) = @_;
10361 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10362}
10363
10364sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010365{ # check structured type for public fields
10366 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010367}
10368
10369sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010370{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010371 my ($TypePtr, $Skip, $Start, $End) = @_;
10372 return 0 if(not $TypePtr);
10373 if($End==-1) {
10374 $End = keys(%{$TypePtr->{"Memb"}})-1;
10375 }
10376 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10377 {
10378 if($Skip and $Skip->{$MemPos})
10379 { # skip removed/added fields
10380 next;
10381 }
10382 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10383 {
10384 if(isPublic($TypePtr, $MemPos)) {
10385 return ($MemPos+1);
10386 }
10387 }
10388 }
10389 return 0;
10390}
10391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010392sub isReserved($)
10393{ # reserved fields == private
10394 my $MName = $_[0];
10395 if($MName=~/reserved|padding|f_spare/i) {
10396 return 1;
10397 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010398 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010399 return 1;
10400 }
10401 if($MName=~/(pad\d+)/i) {
10402 return 1;
10403 }
10404 return 0;
10405}
10406
10407sub isPublic($$)
10408{
10409 my ($TypePtr, $FieldPos) = @_;
10410 return 0 if(not $TypePtr);
10411 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10412 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10413 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10414 { # by name in C language
10415 # FIXME: add other methods to detect private members
10416 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10417 if($MName=~/priv|abidata|parent_object/i)
10418 { # C-styled private data
10419 return 0;
10420 }
10421 if(lc($MName) eq "abi")
10422 { # ABI information/reserved field
10423 return 0;
10424 }
10425 if(isReserved($MName))
10426 { # reserved fields
10427 return 0;
10428 }
10429 return 1;
10430 }
10431 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10432 { # by access in C++ language
10433 return 1;
10434 }
10435 return 0;
10436}
10437
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010438sub getVTable_Real($$)
10439{
10440 my ($ClassName, $LibVersion) = @_;
10441 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10442 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010443 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010444 if(defined $Type{"VTable"}) {
10445 return %{$Type{"VTable"}};
10446 }
10447 }
10448 return ();
10449}
10450
10451sub cmpVTables($)
10452{
10453 my $ClassName = $_[0];
10454 my $Res = cmpVTables_Real($ClassName, 1);
10455 if($Res==-1) {
10456 $Res = cmpVTables_Model($ClassName);
10457 }
10458 return $Res;
10459}
10460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010461sub cmpVTables_Model($)
10462{
10463 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010464 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010466 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010467 return 1;
10468 }
10469 }
10470 return 0;
10471}
10472
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010473sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010474{
10475 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010476 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10477 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010478 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010479 my %VTable_Old = getVTable_Real($ClassName, 1);
10480 my %VTable_New = getVTable_Real($ClassName, 2);
10481 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010482 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010483 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010484 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010485 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010486 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10487 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010488 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010489 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010491 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010492 my $Entry1 = $VTable_Old{$Offset};
10493 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010494 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010495 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010497 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010499 $Entry1 = simpleVEntry($Entry1);
10500 $Entry2 = simpleVEntry($Entry2);
10501 if($Entry1 ne $Entry2)
10502 { # register as changed
10503 if($Entry1=~/::([^:]+)\Z/)
10504 {
10505 my $M1 = $1;
10506 if($Entry2=~/::([^:]+)\Z/)
10507 {
10508 my $M2 = $1;
10509 if($M1 eq $M2)
10510 { # overridden
10511 next;
10512 }
10513 }
10514 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010515 if(differentDumps("G"))
10516 {
10517 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10518 {
10519 # GCC 4.6.1: -0x00000000000000010
10520 # GCC 4.7.0: -16
10521 next;
10522 }
10523 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010524 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010525 }
10526 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010527 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010528}
10529
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010530sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010531{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010532 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010533 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10534 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010535 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010536 { # already registered
10537 next;
10538 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010539 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010540 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010541 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010542 foreach my $Symbol (@Affected)
10543 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010544 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010545 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010546 "Target"=>$ClassName);
10547 }
10548 }
10549 }
10550}
10551
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010552sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010553{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010554 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010555 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010556 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010557 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010558 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010559 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010560 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010561 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010562 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010563 if($TName_Tid{1}{$ClassName}
10564 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010565 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010566 if(defined $CompleteSignature{1}{$Symbol}
10567 and $CompleteSignature{1}{$Symbol}{"Virt"})
10568 { # override some method in v.1
10569 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010570 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010571 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010572 }
10573 }
10574 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010575 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010576 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010577 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010578 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010579 if($TName_Tid{2}{$ClassName}
10580 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010581 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010582 if(defined $CompleteSignature{2}{$Symbol}
10583 and $CompleteSignature{2}{$Symbol}{"Virt"})
10584 { # override some method in v.2
10585 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010586 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010587 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010588 }
10589 }
10590 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010591 if($Level eq "Binary")
10592 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010593 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010594 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10595 { # check replacements, including pure virtual methods
10596 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10597 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010598 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010599 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10600 if($AddedPos==$RemovedPos)
10601 {
10602 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10603 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10604 last; # other methods will be reported as "added" or "removed"
10605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010606 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010607 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10608 {
10609 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10610 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010611 next;
10612 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010613 my $ProblemType = "Virtual_Replacement";
10614 my @Affected = ($RemovedVFunc);
10615 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10616 { # pure methods
10617 if(not isUsedClass($ClassId, 1, $Level))
10618 { # not a parameter of some exported method
10619 next;
10620 }
10621 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010622
10623 # affected all methods (both virtual and non-virtual ones)
10624 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10625 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010626 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010627 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010628 foreach my $AffectedInt (@Affected)
10629 {
10630 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10631 { # affected exported methods only
10632 next;
10633 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010634 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10635 next;
10636 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010637 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10638 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010639 "Target"=>get_Signature($AddedVFunc, 2),
10640 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010642 }
10643 }
10644 }
10645 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010646 if(not checkDump(1, "2.0")
10647 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010648 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010649 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010650 return;
10651 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010652 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010654 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010655 next if(not $ClassId_Old);
10656 if(not isCreatable($ClassId_Old, 1))
10657 { # skip classes without public constructors (including auto-generated)
10658 # example: class has only a private exported or private inline constructor
10659 next;
10660 }
10661 if($ClassName=~/>/)
10662 { # skip affected template instances
10663 next;
10664 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010665 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010666 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010667 if(not $ClassId_New) {
10668 next;
10669 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010670 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010671 if($Class_New{"Type"}!~/Class|Struct/)
10672 { # became typedef
10673 if($Level eq "Binary") {
10674 next;
10675 }
10676 if($Level eq "Source")
10677 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010678 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010679 if($Class_New{"Type"}!~/Class|Struct/) {
10680 next;
10681 }
10682 $ClassId_New = $Class_New{"Tid"};
10683 }
10684 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010685
10686 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10687 { # incomplete info in the ABI dump
10688 next;
10689 }
10690
10691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10693 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 +040010694
10695 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10696 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10697
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010698 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010699 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10700 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010701 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10702 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010703 my $Shift_Old = getShift($ClassId_Old, 1);
10704 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010705 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010706 my ($Added, $Removed) = (0, 0);
10707 my @StableBases_Old = ();
10708 foreach my $BaseId (@Bases_Old)
10709 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010710 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010711 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010712 push(@StableBases_Old, $BaseId);
10713 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010714 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010715 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010716 { # removed base
10717 # excluding namespace::SomeClass to SomeClass renaming
10718 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010719 if($Level eq "Binary")
10720 { # Binary-level
10721 if($Shift_Old ne $Shift_New)
10722 { # affected fields
10723 if(havePubFields(\%Class_Old)) {
10724 $ProblemKind .= "_And_Shift";
10725 }
10726 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10727 $ProblemKind .= "_And_Size";
10728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010729 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010730 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10731 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010732 { # affected v-table
10733 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010734 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 }
10736 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010737 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010738 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10739 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010740 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10741 {
10742 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10743 if($ProblemKind=~/VTable/) {
10744 $VTableChanged_M{$SubName}=1;
10745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010746 }
10747 }
10748 foreach my $Interface (@Affected)
10749 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010750 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10751 next;
10752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010753 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010754 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010755 "Target"=>$BaseName,
10756 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10757 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10758 "Shift"=>abs($Shift_New-$Shift_Old) );
10759 }
10760 $Removed+=1;
10761 }
10762 }
10763 my @StableBases_New = ();
10764 foreach my $BaseId (@Bases_New)
10765 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010766 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010767 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010768 push(@StableBases_New, $BaseId);
10769 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010770 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010771 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010772 { # added base
10773 # excluding namespace::SomeClass to SomeClass renaming
10774 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010775 if($Level eq "Binary")
10776 { # Binary-level
10777 if($Shift_Old ne $Shift_New)
10778 { # affected fields
10779 if(havePubFields(\%Class_Old)) {
10780 $ProblemKind .= "_And_Shift";
10781 }
10782 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10783 $ProblemKind .= "_And_Size";
10784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010786 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10787 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010788 { # affected v-table
10789 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010790 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010791 }
10792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010793 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010794 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10795 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010796 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10797 {
10798 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10799 if($ProblemKind=~/VTable/) {
10800 $VTableChanged_M{$SubName}=1;
10801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010802 }
10803 }
10804 foreach my $Interface (@Affected)
10805 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010806 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10807 next;
10808 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010809 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010810 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010811 "Target"=>$BaseName,
10812 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10813 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10814 "Shift"=>abs($Shift_New-$Shift_Old) );
10815 }
10816 $Added+=1;
10817 }
10818 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010819 if($Level eq "Binary")
10820 { # Binary-level
10821 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010822 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10823 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010824 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010825 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010826 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010827 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010828 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010829 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10830 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010831 if($NewPos!=$OldPos)
10832 { # changed position of the base class
10833 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010835 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10836 next;
10837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010838 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10839 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010840 "Target"=>$BaseName,
10841 "Old_Value"=>$OldPos-1,
10842 "New_Value"=>$NewPos-1 );
10843 }
10844 }
10845 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10846 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10847 { # became non-virtual base
10848 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10849 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010850 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10851 next;
10852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10854 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010855 "Target"=>$BaseName );
10856 }
10857 }
10858 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10859 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10860 { # became virtual base
10861 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10862 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010863 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10864 next;
10865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010866 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10867 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010868 "Target"=>$BaseName );
10869 }
10870 }
10871 }
10872 }
10873 # detect size changes in base classes
10874 if($Shift_Old!=$Shift_New)
10875 { # size of allocable class
10876 foreach my $BaseId (@StableBases_Old)
10877 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010878 my %BaseType = get_Type($BaseId, 1);
10879 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010880 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010881 if($Size_Old ne $Size_New
10882 and $Size_Old and $Size_New)
10883 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010884 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010885 if(isCopyingClass($BaseId, 1)) {
10886 $ProblemType = "Size_Of_Copying_Class";
10887 }
10888 elsif($AllocableClass{1}{$BaseType{"Name"}})
10889 {
10890 if($Size_New>$Size_Old)
10891 { # increased size
10892 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010894 else
10895 { # decreased size
10896 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10897 if(not havePubFields(\%Class_Old))
10898 { # affected class has no public members
10899 next;
10900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010902 }
10903 next if(not $ProblemType);
10904 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10905 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010906 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10907 next;
10908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10910 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010911 "Target"=>$BaseType{"Name"},
10912 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10913 "New_Size"=>$Size_New*$BYTE_SIZE );
10914 }
10915 }
10916 }
10917 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010918 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010919 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010920 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010921 { # compare virtual tables size in base classes
10922 my $VShift_Old = getVShift($ClassId_Old, 1);
10923 my $VShift_New = getVShift($ClassId_New, 2);
10924 if($VShift_Old ne $VShift_New)
10925 { # changes in the base class or changes in the list of base classes
10926 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10927 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10928 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010929 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 foreach my $BaseId (@AllBases_Old)
10931 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010932 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010933 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010934 { # lost base
10935 next;
10936 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010937 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10938 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010939 if($VSize_Old!=$VSize_New)
10940 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010941 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010942 { # TODO: affected non-virtual methods?
10943 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010944 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10945 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010947 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010948 { # skip interfaces that have not changed the absolute virtual position
10949 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010950 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010951 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10952 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010954 $VTableChanged_M{$BaseType{"Name"}} = 1;
10955 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010956 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10957 { # the reason of the layout change: added virtual functions
10958 next if($VirtualReplacement{$VirtFunc});
10959 my $ProblemType = "Added_Virtual_Method";
10960 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10961 $ProblemType = "Added_Pure_Virtual_Method";
10962 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010963 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010964 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010965 "Target"=>get_Signature($VirtFunc, 2) );
10966 }
10967 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10968 { # the reason of the layout change: removed virtual functions
10969 next if($VirtualReplacement{$VirtFunc});
10970 my $ProblemType = "Removed_Virtual_Method";
10971 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10972 $ProblemType = "Removed_Pure_Virtual_Method";
10973 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010974 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010975 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 "Target"=>get_Signature($VirtFunc, 1) );
10977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010978 }
10979 }
10980 }
10981 }
10982 }
10983 }
10984 }
10985}
10986
10987sub isCreatable($$)
10988{
10989 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010990 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010991 or isCopyingClass($ClassId, $LibVersion)) {
10992 return 1;
10993 }
10994 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10995 { # Fix for incomplete data: if this class has
10996 # a base class then it should also has a constructor
10997 return 1;
10998 }
10999 if($ReturnedClass{$LibVersion}{$ClassId})
11000 { # returned by some method of this class
11001 # or any other class
11002 return 1;
11003 }
11004 return 0;
11005}
11006
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011008{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011009 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011010 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11011 { # parameter of some exported method
11012 return 1;
11013 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011014 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11015 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011016 { # method from target class
11017 return 1;
11018 }
11019 return 0;
11020}
11021
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011023{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011024 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011025 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011026 # - virtual
11027 # - pure-virtual
11028 # - non-virtual
11029 if($CompleteSignature{1}{$Interface}{"Data"})
11030 { # global data is not affected
11031 return;
11032 }
11033 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011034 if(not $Class_Id) {
11035 return;
11036 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011037 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011038 if(cmpVTables_Real($CName, 1)==0)
11039 { # no changes
11040 return;
11041 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 $CheckedTypes{$Level}{$CName} = 1;
11043 if($Level eq "Binary")
11044 { # Binary-level
11045 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11046 and not isUsedClass($Class_Id, 1, $Level))
11047 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011048 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011049 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011050 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011051 }
11052 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11053 {
11054 if(defined $VirtualTable{2}{$CName}{$Func}
11055 and defined $CompleteSignature{2}{$Func})
11056 {
11057 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11058 and $CompleteSignature{2}{$Func}{"PureVirt"})
11059 { # became pure virtual
11060 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11061 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011062 "Target"=>get_Signature_M($Func, 1) );
11063 $VTableChanged_M{$CName} = 1;
11064 }
11065 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11066 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11067 { # became non-pure virtual
11068 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11069 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011070 "Target"=>get_Signature_M($Func, 1) );
11071 $VTableChanged_M{$CName} = 1;
11072 }
11073 }
11074 }
11075 if($Level eq "Binary")
11076 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 # check virtual table structure
11078 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11079 {
11080 next if($Interface eq $AddedVFunc);
11081 next if($VirtualReplacement{$AddedVFunc});
11082 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11083 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11084 { # pure virtual methods affect all others (virtual and non-virtual)
11085 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011086 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011087 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011088 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011089 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011090 elsif(not defined $VirtualTable{1}{$CName}
11091 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011092 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011093 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011094 { # became polymorphous class, added v-table pointer
11095 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011096 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011097 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011098 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 }
11100 else
11101 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011102 my $VSize_Old = getVTable_Size($CName, 1);
11103 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011104 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011105 if(isCopyingClass($Class_Id, 1))
11106 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11107 my $ProblemType = "Added_Virtual_Method";
11108 if(isLeafClass($Class_Id, 1)) {
11109 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11110 }
11111 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11112 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011113 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011114 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011115 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011116 else
11117 {
11118 my $ProblemType = "Added_Virtual_Method";
11119 if(isLeafClass($Class_Id, 1)) {
11120 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11121 }
11122 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11123 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011125 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011127 }
11128 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11130 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011132 if(defined $VirtualTable{1}{$CName}
11133 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011134 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011135 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11136 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011137
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011138 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011139 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011140 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11141 foreach my $ASymbol (@Affected)
11142 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011143 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11144 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011145 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011146 next;
11147 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011148 }
11149 $CheckedSymbols{$Level}{$ASymbol} = 1;
11150 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11151 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011152 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011153 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011156 }
11157 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011158 else {
11159 # safe
11160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011161 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011162 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11163 {
11164 next if($VirtualReplacement{$RemovedVFunc});
11165 if($RemovedVFunc eq $Interface
11166 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11167 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011168 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011169 next;
11170 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011171 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011172 { # became non-polymorphous class, removed v-table pointer
11173 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11174 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011175 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011176 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011177 }
11178 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11179 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11180 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011181 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011182 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011183 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11184 next;
11185 }
11186 my $VPos_New = -1;
11187 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011188 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011189 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11190 }
11191 else
11192 {
11193 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 next;
11195 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011196 }
11197 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11198 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11199 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11200 {
11201 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11202 foreach my $ASymbol (@Affected)
11203 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011204 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11205 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011206 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011207 next;
11208 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011209 }
11210 my $ProblemType = "Removed_Virtual_Method";
11211 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11212 $ProblemType = "Removed_Pure_Virtual_Method";
11213 }
11214 $CheckedSymbols{$Level}{$ASymbol} = 1;
11215 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11216 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011217 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011218 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011220 }
11221 }
11222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011223 }
11224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011225 else
11226 { # Source-level
11227 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011228 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011229 next if($Interface eq $AddedVFunc);
11230 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011231 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011232 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11233 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011234 "Target"=>get_Signature($AddedVFunc, 2) );
11235 }
11236 }
11237 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11238 {
11239 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11240 {
11241 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11242 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011243 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244 }
11245 }
11246 }
11247}
11248
11249sub find_MemberPair_Pos_byName($$)
11250{
11251 my ($Member_Name, $Pair_Type) = @_;
11252 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11253 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11254 {
11255 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11256 {
11257 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11258 $Name=~s/\A[_]+|[_]+\Z//g;
11259 if($Name eq $Member_Name) {
11260 return $MemberPair_Pos;
11261 }
11262 }
11263 }
11264 return "lost";
11265}
11266
11267sub find_MemberPair_Pos_byVal($$)
11268{
11269 my ($Member_Value, $Pair_Type) = @_;
11270 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11271 {
11272 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11273 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11274 return $MemberPair_Pos;
11275 }
11276 }
11277 return "lost";
11278}
11279
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011280sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011281{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011282 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011283 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011284 if( $_->{"T1"} eq $_[0]
11285 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011286 {
11287 return 1;
11288 }
11289 }
11290 return 0;
11291}
11292
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011293sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011294{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011295 my %IDs = (
11296 "T1" => $_[0],
11297 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011298 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011299 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011300}
11301
11302sub isRenamed($$$$$)
11303{
11304 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11305 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11306 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011307 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011308 if(not defined $Type2->{"Memb"}{$MemPos}) {
11309 return "";
11310 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011311 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011312 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011313
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011314 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11315 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011316 if($MemberPair_Pos_Rev eq "lost")
11317 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011318 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11319 { # base type match
11320 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011321 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011322 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11323 { # exact type match
11324 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011326 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11327 { # size match
11328 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011330 if(isReserved($Pair_Name))
11331 { # reserved fields
11332 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011333 }
11334 }
11335 return "";
11336}
11337
11338sub isLastElem($$)
11339{
11340 my ($Pos, $TypeRef) = @_;
11341 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11342 if($Name=~/last|count|max|total/i)
11343 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11344 return 1;
11345 }
11346 elsif($Name=~/END|NLIMITS\Z/)
11347 { # __RLIMIT_NLIMITS
11348 return 1;
11349 }
11350 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11351 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11352 { # NImageFormats, NColorRoles
11353 return 1;
11354 }
11355 return 0;
11356}
11357
11358sub nonComparable($$)
11359{
11360 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011361
11362 my $N1 = $T1->{"Name"};
11363 my $N2 = $T2->{"Name"};
11364
11365 $N1=~s/\A(struct|union|enum) //;
11366 $N2=~s/\A(struct|union|enum) //;
11367
11368 if($N1 ne $N2
11369 and not isAnon($N1)
11370 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011371 { # different names
11372 if($T1->{"Type"} ne "Pointer"
11373 or $T2->{"Type"} ne "Pointer")
11374 { # compare base types
11375 return 1;
11376 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011377 if($N1!~/\Avoid\s*\*/
11378 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011379 {
11380 return 1;
11381 }
11382 }
11383 elsif($T1->{"Type"} ne $T2->{"Type"})
11384 { # different types
11385 if($T1->{"Type"} eq "Class"
11386 and $T2->{"Type"} eq "Struct")
11387 { # "class" to "struct"
11388 return 0;
11389 }
11390 elsif($T2->{"Type"} eq "Class"
11391 and $T1->{"Type"} eq "Struct")
11392 { # "struct" to "class"
11393 return 0;
11394 }
11395 else
11396 { # "class" to "enum"
11397 # "union" to "class"
11398 # ...
11399 return 1;
11400 }
11401 }
11402 return 0;
11403}
11404
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011405sub isOpaque($)
11406{
11407 my $T = $_[0];
11408 if(not defined $T->{"Memb"})
11409 {
11410 return 1;
11411 }
11412 return 0;
11413}
11414
11415sub removeVPtr($)
11416{ # support for old ABI dumps
11417 my $TPtr = $_[0];
11418 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11419 if($#Pos>=1)
11420 {
11421 foreach my $Pos (0 .. $#Pos-1)
11422 {
11423 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11424 }
11425 delete($TPtr->{"Memb"}{$#Pos});
11426 }
11427}
11428
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011429sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011430{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011431 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011432 return {} if(not $Type1_Id or not $Type2_Id);
11433
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011434 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011435 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011436 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011437 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011438
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011439 my %Type1 = get_Type($Type1_Id, 1);
11440 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011441 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011442 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011443 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011444
11445 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011446 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11447 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011448
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011449 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11450
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011451 my %SubProblems = ();
11452
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011453 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11454 {
11455 if($Type1_Pure{"Type"}=~/Struct|Union/
11456 and $Type2_Pure{"Type"}=~/Struct|Union/)
11457 {
11458 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11459 {
11460 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11461 "Target"=>$Type1_Pure{"Name"},
11462 "Type_Name"=>$Type1_Pure{"Name"} );
11463
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011464 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011465 }
11466 }
11467 }
11468
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011469 if(not $Type1_Pure{"Size"}
11470 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011471 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011472 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11473 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11474 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011475 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011476 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011477 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011478 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011479 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011480 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011481 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011482 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11483 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11484 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011485
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011486 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11487 { # support for old ABI dumps
11488 # _vptr field added in 3.0
11489 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11490 {
11491 if(defined $Type2_Pure{"Memb"}
11492 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11493 {
11494 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11495 delete($Type2_Pure{"Memb"}{0});
11496 }
11497 else {
11498 removeVPtr(\%Type2_Pure);
11499 }
11500 }
11501 }
11502 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11503 {
11504 if(defined $Type1_Pure{"Memb"}
11505 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11506 {
11507 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11508 delete($Type1_Pure{"Memb"}{0});
11509 }
11510 else {
11511 removeVPtr(\%Type1_Pure);
11512 }
11513 }
11514 }
11515 }
11516
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011517 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11518 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011519
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011520 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11521 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11522 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011523 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011524 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11525 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011526 if($Base_1{"Name"} ne $Base_2{"Name"})
11527 {
11528 if(differentDumps("G")
11529 or differentDumps("V"))
11530 { # different GCC versions or different dumps
11531 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11532 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11533 # std::__va_list and __va_list
11534 $Base_1{"Name"}=~s/\A(\w+::)+//;
11535 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011536 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11537 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011539 }
11540 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11541 and $Base_1{"Name"} ne $Base_2{"Name"})
11542 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011543 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011544 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011545 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011546 {
11547 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11548 "Target"=>$Typedef_1{"Name"},
11549 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011550 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11551 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11552 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011553 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11554 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011555 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011556 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011557 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11558 {
11559 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11560 "Target"=>$Typedef_1{"Name"},
11561 "Type_Name"=>$Typedef_1{"Name"},
11562 "Old_Value"=>$Base_1{"Name"},
11563 "New_Value"=>$Base_2{"Name"} );
11564 }
11565 else
11566 {
11567 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11568 "Target"=>$Typedef_1{"Name"},
11569 "Type_Name"=>$Typedef_1{"Name"},
11570 "Old_Value"=>$Base_1{"Name"},
11571 "New_Value"=>$Base_2{"Name"} );
11572 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011574 }
11575 }
11576 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11577 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011578 my $TT1 = $Type1_Pure{"Type"};
11579 my $TT2 = $Type2_Pure{"Type"};
11580
11581 if($TT1 ne $TT2
11582 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011583 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011584 my $Short1 = $Type1_Pure{"Name"};
11585 my $Short2 = $Type2_Pure{"Name"};
11586
11587 $Short1=~s/\A\Q$TT1\E //ig;
11588 $Short2=~s/\A\Q$TT2\E //ig;
11589
11590 if($Short1 eq $Short2)
11591 {
11592 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11593 "Target"=>$Type1_Pure{"Name"},
11594 "Type_Name"=>$Type1_Pure{"Name"},
11595 "Old_Value"=>lc($Type1_Pure{"Type"}),
11596 "New_Value"=>lc($Type2_Pure{"Type"}) );
11597 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011598 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011599 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011601 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11603 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11604 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11605 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011606 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011607 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011608 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011609 {
11610 my $ProblemKind = "DataType_Size";
11611 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011612 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011613 {
11614 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11615 $ProblemKind = "Size_Of_Copying_Class";
11616 }
11617 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11618 {
11619 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11620 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11621 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011622 else
11623 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011624 # descreased size of allocable class
11625 # it has no special effects
11626 }
11627 }
11628 }
11629 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11630 "Target"=>$Type1_Pure{"Name"},
11631 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011632 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011633 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 }
11635 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011636 if(defined $Type1_Pure{"BaseType"}
11637 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011638 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011639 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11640 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011641 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011642 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11643 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011644 }
11645 }
11646 }
11647 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11648 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11649 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11650 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11651 { # detect removed and renamed fields
11652 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11653 next if(not $Member_Name);
11654 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);
11655 if($MemberPair_Pos eq "lost")
11656 {
11657 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11658 {
11659 if(isUnnamed($Member_Name))
11660 { # support for old-version dumps
11661 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011662 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011663 next;
11664 }
11665 }
11666 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11667 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011668 $RenamedField{$Member_Pos} = $RenamedTo;
11669 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011670 }
11671 else
11672 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011673 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011674 }
11675 }
11676 elsif($Type1_Pure{"Type"} eq "Enum")
11677 {
11678 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11679 next if($Member_Value1 eq "");
11680 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11681 if($MemberPair_Pos ne "lost")
11682 { # renamed
11683 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11684 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11685 if($MemberPair_Pos_Rev eq "lost")
11686 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011687 $RenamedField{$Member_Pos} = $RenamedTo;
11688 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011689 }
11690 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011691 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011692 }
11693 }
11694 else
11695 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011696 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011697 }
11698 }
11699 }
11700 else
11701 { # related
11702 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11703 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11704 }
11705 }
11706 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11707 { # detect added fields
11708 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11709 next if(not $Member_Name);
11710 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);
11711 if($MemberPair_Pos eq "lost")
11712 {
11713 if(isUnnamed($Member_Name))
11714 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011715 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011716 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011717 next;
11718 }
11719 }
11720 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11721 {
11722 if(not $RenamedField_Rev{$Member_Pos})
11723 { # added
11724 $AddedField{$Member_Pos}=1;
11725 }
11726 }
11727 }
11728 }
11729 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11730 { # detect moved fields
11731 my (%RelPos, %RelPosName, %AbsPos) = ();
11732 my $Pos = 0;
11733 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11734 { # relative positions in 1st version
11735 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11736 next if(not $Member_Name);
11737 if(not $RemovedField{$Member_Pos})
11738 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011739 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011740 $RelPosName{1}{$Pos} = $Member_Name;
11741 $AbsPos{1}{$Pos++} = $Member_Pos;
11742 }
11743 }
11744 $Pos = 0;
11745 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11746 { # relative positions in 2nd version
11747 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11748 next if(not $Member_Name);
11749 if(not $AddedField{$Member_Pos})
11750 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011751 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011752 $RelPosName{2}{$Pos} = $Member_Name;
11753 $AbsPos{2}{$Pos++} = $Member_Pos;
11754 }
11755 }
11756 foreach my $Member_Name (keys(%{$RelPos{1}}))
11757 {
11758 my $RPos1 = $RelPos{1}{$Member_Name};
11759 my $AbsPos1 = $NameToPosA{$Member_Name};
11760 my $Member_Name2 = $Member_Name;
11761 if(my $RenamedTo = $RenamedField{$AbsPos1})
11762 { # renamed
11763 $Member_Name2 = $RenamedTo;
11764 }
11765 my $RPos2 = $RelPos{2}{$Member_Name2};
11766 if($RPos2 ne "" and $RPos1 ne $RPos2)
11767 { # different relative positions
11768 my $AbsPos2 = $NameToPosB{$Member_Name2};
11769 if($AbsPos1 ne $AbsPos2)
11770 { # different absolute positions
11771 my $ProblemType = "Moved_Field";
11772 if(not isPublic(\%Type1_Pure, $AbsPos1))
11773 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011774 if($Level eq "Source") {
11775 next;
11776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011777 $ProblemType = "Moved_Private_Field";
11778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011779 if($Level eq "Binary"
11780 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011781 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011782 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011783 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011784 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011785 if($MemSize1 ne $MemSize2) {
11786 $ProblemType .= "_And_Size";
11787 }
11788 }
11789 if($ProblemType eq "Moved_Private_Field") {
11790 next;
11791 }
11792 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11793 "Target"=>$Member_Name,
11794 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011795 "Old_Value"=>$RPos1,
11796 "New_Value"=>$RPos2 );
11797 }
11798 }
11799 }
11800 }
11801 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011802 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011803 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11804 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011805 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011806 if(my $RenamedTo = $RenamedField{$Member_Pos})
11807 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011808 if(defined $Constants{2}{$Member_Name})
11809 {
11810 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11811 { # define OLD NEW
11812 next; # Safe
11813 }
11814 }
11815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011816 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11817 {
11818 if(isPublic(\%Type1_Pure, $Member_Pos))
11819 {
11820 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11821 "Target"=>$Member_Name,
11822 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011823 "Old_Value"=>$Member_Name,
11824 "New_Value"=>$RenamedTo );
11825 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011826 elsif(isReserved($Member_Name))
11827 {
11828 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11829 "Target"=>$Member_Name,
11830 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011831 "Old_Value"=>$Member_Name,
11832 "New_Value"=>$RenamedTo );
11833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011834 }
11835 elsif($Type1_Pure{"Type"} eq "Enum")
11836 {
11837 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11838 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11839 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 "Old_Value"=>$Member_Name,
11841 "New_Value"=>$RenamedTo );
11842 }
11843 }
11844 elsif($RemovedField{$Member_Pos})
11845 { # removed
11846 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11847 {
11848 my $ProblemType = "Removed_Field";
11849 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011850 or isUnnamed($Member_Name))
11851 {
11852 if($Level eq "Source") {
11853 next;
11854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011855 $ProblemType = "Removed_Private_Field";
11856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011857 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011858 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011859 {
11860 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11861 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011862 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 +040011863 { # changed offset
11864 $ProblemType .= "_And_Layout";
11865 }
11866 }
11867 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11868 { # affected size
11869 $ProblemType .= "_And_Size";
11870 }
11871 }
11872 if($ProblemType eq "Removed_Private_Field") {
11873 next;
11874 }
11875 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11876 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011877 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011878 }
11879 elsif($Type2_Pure{"Type"} eq "Union")
11880 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011881 if($Level eq "Binary"
11882 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011883 {
11884 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11885 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011886 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011887 }
11888 else
11889 {
11890 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11891 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011892 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011893 }
11894 }
11895 elsif($Type1_Pure{"Type"} eq "Enum")
11896 {
11897 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11898 "Target"=>$Member_Name,
11899 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011900 "Old_Value"=>$Member_Name );
11901 }
11902 }
11903 else
11904 { # changed
11905 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11906 if($Type1_Pure{"Type"} eq "Enum")
11907 {
11908 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11909 next if($Member_Value1 eq "");
11910 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11911 next if($Member_Value2 eq "");
11912 if($Member_Value1 ne $Member_Value2)
11913 {
11914 my $ProblemType = "Enum_Member_Value";
11915 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11916 $ProblemType = "Enum_Last_Member_Value";
11917 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011918 if($SkipConstants{1}{$Member_Name}) {
11919 $ProblemType = "Enum_Private_Member_Value";
11920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011921 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11922 "Target"=>$Member_Name,
11923 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011924 "Old_Value"=>$Member_Value1,
11925 "New_Value"=>$Member_Value2 );
11926 }
11927 }
11928 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11929 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011930 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11931 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11932
11933 if($Access1 ne "private"
11934 and $Access2 eq "private")
11935 {
11936 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11937 "Target"=>$Member_Name,
11938 "Type_Name"=>$Type1_Pure{"Name"});
11939 }
11940 elsif($Access1 ne "protected"
11941 and $Access1 ne "private"
11942 and $Access2 eq "protected")
11943 {
11944 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11945 "Target"=>$Member_Name,
11946 "Type_Name"=>$Type1_Pure{"Name"});
11947 }
11948
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011949 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11950 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011951 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011952 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11953 $SizeV1 = $BSize1;
11954 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011955 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011956 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11957 $SizeV2 = $BSize2;
11958 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011959 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11960 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011961 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011962 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011963 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011964 {
11965 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11966 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11967 { # field size change (including anon-structures and unions)
11968 # - same types
11969 # - unnamed types
11970 # - bitfields
11971 my $ProblemType = "Field_Size";
11972 if(not isPublic(\%Type1_Pure, $Member_Pos)
11973 or isUnnamed($Member_Name))
11974 { # should not be accessed by applications, goes to "Low Severity"
11975 # example: "abidata" members in GStreamer types
11976 $ProblemType = "Private_".$ProblemType;
11977 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011978 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 +040011979 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011980 if($Type2_Pure{"Type"} ne "Union"
11981 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011982 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011983 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 +040011984 { # changed offset
11985 $ProblemType .= "_And_Layout";
11986 }
11987 }
11988 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11989 $ProblemType .= "_And_Type_Size";
11990 }
11991 }
11992 if($ProblemType eq "Private_Field_Size")
11993 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011994 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011995 if($ProblemType eq "Field_Size")
11996 {
11997 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11998 { # Low severity
11999 $ProblemType = "Struct_Field_Size_Increased";
12000 }
12001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012002 if($ProblemType)
12003 { # register a problem
12004 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12005 "Target"=>$Member_Name,
12006 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012007 "Old_Size"=>$SizeV1,
12008 "New_Size"=>$SizeV2);
12009 }
12010 }
12011 }
12012 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12013 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12014 { # do NOT check bitfield type changes
12015 next;
12016 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012017 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012018 {
12019 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12020 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12021 {
12022 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12023 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012024 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012025 }
12026 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12027 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12028 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012029 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012030 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012031 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012032 }
12033 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012034 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12035 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012036 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012037 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12038 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012039
12040 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012041 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012042 or $ProblemType eq "Field_Type_And_Size"
12043 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012044 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012045 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012046 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012047 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012048 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012049 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012050 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012051 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012052 }
12053 }
12054 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12055 {
12056 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012057 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012058 }
12059 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012060 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012061 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012062 }
12063 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12064 {
12065 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012066 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012067 }
12068 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012069 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012070 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012071 }
12072 }
12073 }
12074
12075 if($Level eq "Source")
12076 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012077 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012078 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012079 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12080 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012081
12082 if($ProblemType eq "Field_Type")
12083 {
12084 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012085 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012086 }
12087 }
12088 }
12089 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012090
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012091 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012092 {
12093 my $ProblemType_Init = $ProblemType;
12094 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012095 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012096 if(not isPublic(\%Type1_Pure, $Member_Pos)
12097 or isUnnamed($Member_Name)) {
12098 $ProblemType = "Private_".$ProblemType;
12099 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012100 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 +040012101 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012102 if($Type2_Pure{"Type"} ne "Union"
12103 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012104 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012105 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 +040012106 { # changed offset
12107 $ProblemType .= "_And_Layout";
12108 }
12109 }
12110 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12111 $ProblemType .= "_And_Type_Size";
12112 }
12113 }
12114 }
12115 else
12116 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012117 # TODO: Private_Field_Type rule?
12118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012119 if(not isPublic(\%Type1_Pure, $Member_Pos)
12120 or isUnnamed($Member_Name)) {
12121 next;
12122 }
12123 }
12124 if($ProblemType eq "Private_Field_Type_And_Size")
12125 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012126 }
12127 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12128 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012129 "Type_Name"=>$Type1_Pure{"Name"});
12130
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012131 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012132 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012133 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012134 }
12135 }
12136 if(not isPublic(\%Type1_Pure, $Member_Pos))
12137 { # do NOT check internal type changes
12138 next;
12139 }
12140 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012141 { # checking member type changes
12142 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12143
12144 my %DupProblems = ();
12145
12146 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012147 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012148 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012150 if(not defined $AllAffected)
12151 {
12152 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12153 next;
12154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012155 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012156
12157 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12158 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12159
12160 if(not defined $AllAffected)
12161 {
12162 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012163 }
12164 }
12165 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012166
12167 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012168 }
12169 }
12170 }
12171 }
12172 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12173 { # checking added members, public and private
12174 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12175 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012176 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 if($AddedField{$Member_Pos})
12178 { # added
12179 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12180 {
12181 my $ProblemType = "Added_Field";
12182 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012183 or isUnnamed($Member_Name))
12184 {
12185 if($Level eq "Source") {
12186 next;
12187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012188 $ProblemType = "Added_Private_Field";
12189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012190 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012191 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012192 {
12193 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12194 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012195 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 +040012196 { # changed offset
12197 $ProblemType .= "_And_Layout";
12198 }
12199 }
12200 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12201 $ProblemType .= "_And_Size";
12202 }
12203 }
12204 if($ProblemType eq "Added_Private_Field")
12205 { # skip added private fields
12206 next;
12207 }
12208 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12209 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012210 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012211 }
12212 elsif($Type2_Pure{"Type"} eq "Union")
12213 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012214 if($Level eq "Binary"
12215 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012216 {
12217 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12218 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012219 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012220 }
12221 else
12222 {
12223 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12224 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012225 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012226 }
12227 }
12228 elsif($Type2_Pure{"Type"} eq "Enum")
12229 {
12230 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12231 next if($Member_Value eq "");
12232 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12233 "Target"=>$Member_Name,
12234 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012235 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012236 }
12237 }
12238 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012239
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012240 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012241 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242}
12243
12244sub isUnnamed($) {
12245 return $_[0]=~/\Aunnamed\d+\Z/;
12246}
12247
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012248sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012249{
12250 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012251 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12252 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12253 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12254 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012255 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012256 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012257 }
12258 return $TypeName;
12259}
12260
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012261sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012263 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012264 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012265 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12266 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012267 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012268 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12269 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012270 return () if(not $Type{"Type"});
12271 if($Type{"Type"} ne $Type_Type)
12272 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012273 return () if(not $Type{"BaseType"});
12274 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012276 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012277 return %Type;
12278}
12279
12280my %TypeSpecAttributes = (
12281 "Const" => 1,
12282 "Volatile" => 1,
12283 "ConstVolatile" => 1,
12284 "Restrict" => 1,
12285 "Typedef" => 1
12286);
12287
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012288sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012290 my ($TypeId, $Info) = @_;
12291 if(not $TypeId or not $Info
12292 or not $Info->{$TypeId}) {
12293 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012294 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012295 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12296 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12297 }
12298 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012299 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012300 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012301 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012303 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 return %Type;
12305}
12306
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012307sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012308{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012309 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012310 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012311 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12312 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012314 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12315 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012316 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12317 my $PLevel = 0;
12318 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12319 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012320 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012321 return $PLevel if(not $Type{"BaseType"});
12322 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12323 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12324 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012325}
12326
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012327sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012328{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012329 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012330 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012331 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12332 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012334 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12335 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012336 return %Type if(not $Type{"BaseType"});
12337 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012338 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012339 return %Type;
12340}
12341
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012342sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012343{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012344 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012345 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012346 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12347 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012348 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012349 my $Qual = "";
12350 if($Type{"Type"} eq "Pointer") {
12351 $Qual .= "*";
12352 }
12353 elsif($Type{"Type"} eq "Ref") {
12354 $Qual .= "&";
12355 }
12356 elsif($Type{"Type"} eq "ConstVolatile") {
12357 $Qual .= "const volatile";
12358 }
12359 elsif($Type{"Type"} eq "Const"
12360 or $Type{"Type"} eq "Volatile"
12361 or $Type{"Type"} eq "Restrict") {
12362 $Qual .= lc($Type{"Type"});
12363 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012364 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365 return $BQual.$Qual;
12366}
12367
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012368sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012369{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012370 my ($TypeId, $Info) = @_;
12371 if(not $TypeId or not $Info
12372 or not $Info->{$TypeId}) {
12373 return ();
12374 }
12375 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012376 return %Type if(not $Type{"BaseType"});
12377 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012378 {
12379 if($Info->{$BTid}) {
12380 return %{$Info->{$BTid}};
12381 }
12382 else { # something is going wrong
12383 return ();
12384 }
12385 }
12386 else {
12387 return %Type;
12388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012389}
12390
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012391sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012392{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012393 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012394 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012395 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12396 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012397}
12398
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012399sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012400{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012401 my $Symbol = $_[0];
12402 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12403}
12404
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012405sub isInLineInst($$$) {
12406 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12407}
12408
12409sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012411 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012412 if($CheckObjectsOnly)
12413 {
12414 if($Symbol!~/\A(_Z|\?)/) {
12415 return 0;
12416 }
12417 if(my $Signature = $tr_name{$Symbol})
12418 {
12419 if(index($Signature,">")==-1) {
12420 return 0;
12421 }
12422 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12423 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012424 if(index($ShortName,"<")!=-1
12425 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012426 return 1;
12427 }
12428 }
12429 }
12430 }
12431 else
12432 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012433 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012434 {
12435 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12436 {
12437 if(index($ClassName,"<")!=-1) {
12438 return 1;
12439 }
12440 }
12441 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012442 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012443 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012444 if(index($ShortName,"<")!=-1
12445 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012446 return 1;
12447 }
12448 }
12449 }
12450 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451}
12452
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012453sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012454{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012455 my ($Symbol, $SInfo, $LibVersion) = @_;
12456 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012457 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012458 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012459 { # class specialization
12460 return 1;
12461 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012462 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012463 { # method specialization
12464 return 1;
12465 }
12466 }
12467 return 0;
12468}
12469
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012470sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012471{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012472 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012473 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012474 { # non-public global data
12475 return 0;
12476 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012477
12478 if(defined $SkipInternal)
12479 {
12480 return 0 if($Symbol=~/($SkipInternal)/);
12481 }
12482
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012483 if($CheckObjectsOnly) {
12484 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12485 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012486 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012487 { # support for old ABI dumps in --headers-only mode
12488 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12489 {
12490 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12491 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012492 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012493 if(not $PType or $PType eq "Unknown") {
12494 return 0;
12495 }
12496 }
12497 }
12498 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012499 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012500 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 if($SkipSymbols{$LibVersion}{$Symbol})
12502 { # user defined symbols to ignore
12503 return 0;
12504 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012505 if($SymbolsListPath and not $SymbolsList{$Symbol})
12506 { # user defined symbols
12507 return 0;
12508 }
12509 if($AppPath and not $SymbolsList_App{$Symbol})
12510 { # user defined symbols (in application)
12511 return 0;
12512 }
12513
12514 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12515
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012516 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12517 if(not $NameSpace and $ClassId)
12518 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012519 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012520 }
12521 if($NameSpace)
12522 { # user defined namespaces to ignore
12523 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12524 return 0;
12525 }
12526 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12527 { # nested namespaces
12528 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12529 return 0;
12530 }
12531 }
12532 }
12533 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12534 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012535 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012536 { # --skip-headers or <skip_headers> (not <skip_including>)
12537 if($Skip==1) {
12538 return 0;
12539 }
12540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012542 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012543 { # user defined types
12544 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12545
12546 if(not $TypesList{$CName})
12547 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012548 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12549 {
12550 $CName=~s/\A\Q$NS\E\:\://g;
12551 }
12552
12553 if(not $TypesList{$CName})
12554 {
12555 my $Found = 0;
12556
12557 while($CName=~s/\:\:.+?\Z//)
12558 {
12559 if($TypesList{$CName})
12560 {
12561 $Found = 1;
12562 last;
12563 }
12564 }
12565
12566 if(not $Found) {
12567 return 0;
12568 }
12569 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012570 }
12571 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012572
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012573 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12574 { # non-target symbols
12575 return 0;
12576 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012577 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012578 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012579 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012580 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012581 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012582 return 0;
12583 }
12584 }
12585 else
12586 {
12587 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012588 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012589 {
12590 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12591 { # inline virtual methods
12592 if($Type=~/InlineVirt/) {
12593 return 1;
12594 }
12595 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12596 if(not $Allocable)
12597 { # check bases
12598 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12599 {
12600 if(not isCopyingClass($DCId, $LibVersion))
12601 { # exists a derived class without default c-tor
12602 $Allocable=1;
12603 last;
12604 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012607 if(not $Allocable) {
12608 return 0;
12609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012611 else
12612 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012613 return 0;
12614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012616 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012617 }
12618 }
12619 return 1;
12620}
12621
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012622sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012623{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012624 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12626 {
12627 if(link_symbol($Symbol, 1, "+Deps"))
12628 { # linker can find a new symbol
12629 # in the old-version library
12630 # So, it's not a new symbol
12631 next;
12632 }
12633 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012634 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635 next;
12636 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012637 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012638 }
12639}
12640
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012641sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012643 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012644 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12645 {
12646 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012647 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 }
12649 if(link_symbol($Symbol, 2, "+Deps"))
12650 { # linker can find an old symbol
12651 # in the new-version library
12652 next;
12653 }
12654 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012655 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012656 next;
12657 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012658 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 }
12660}
12661
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012662sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012663{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012664 my $Level = $_[0];
12665 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 { # checking added symbols
12667 next if($CompleteSignature{2}{$Symbol}{"Private"});
12668 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012669 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012670 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012671 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012672 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012673 { # checking removed symbols
12674 next if($CompleteSignature{1}{$Symbol}{"Private"});
12675 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012676 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012677 { # skip v-tables for templates, that should not be imported by applications
12678 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012679 if(my $CName = $VTableClass{$Symbol})
12680 {
12681 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12682 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012683 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012684 next;
12685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012686 }
12687 }
12688 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012689 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012690 }
12691 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12692 { # symbols for pure virtual methods cannot be called by clients
12693 next;
12694 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012695 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012696 }
12697}
12698
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012699sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012700{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012701 my ($LibVersion, $V) = @_;
12702 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12703 return $Cache{"checkDump"}{$LibVersion}{$V};
12704 }
12705 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012706}
12707
12708sub detectAdded_H($)
12709{
12710 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012711 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12712 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012713 if($Level eq "Source")
12714 { # remove symbol version
12715 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12716 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012717
12718 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12719 { # skip artificial constructors
12720 next;
12721 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012722 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012723 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12724 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012725 next;
12726 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012727 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012728 next;
12729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012730 if(not defined $CompleteSignature{1}{$Symbol}
12731 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12732 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012733 if($UsedDump{2}{"SrcBin"})
12734 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012735 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012736 { # support for old and different (!) ABI dumps
12737 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12738 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012739 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012740 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012741 {
12742 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12743 {
12744 if($Lang eq "C")
12745 { # support for old ABI dumps: missed extern "C" functions
12746 next;
12747 }
12748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012749 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012750 else
12751 {
12752 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012753 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012754 next;
12755 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012756 }
12757 }
12758 }
12759 }
12760 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012761 }
12762 }
12763}
12764
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012765sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012766{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12769 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012770 if($Level eq "Source")
12771 { # remove symbol version
12772 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12773 $Symbol=$SN;
12774 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012775 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12776 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012777 next;
12778 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012779 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012780 next;
12781 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012782 if(not defined $CompleteSignature{2}{$Symbol}
12783 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012784 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012785 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012786 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012787 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012788 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012789 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12790 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012791 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012792 if($CheckHeadersOnly)
12793 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012794 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12795 {
12796 if($Lang eq "C")
12797 { # support for old ABI dumps: missed extern "C" functions
12798 next;
12799 }
12800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012802 else
12803 {
12804 if(not link_symbol($Symbol, 1, "-Deps"))
12805 { # skip removed inline symbols
12806 next;
12807 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012808 }
12809 }
12810 }
12811 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012812 if(not checkDump(1, "2.15"))
12813 {
12814 if($Symbol=~/_IT_E\Z/)
12815 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12816 next;
12817 }
12818 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012819 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12820 {
12821 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12822 {
12823 if(defined $Constants{2}{$Short})
12824 {
12825 my $Val = $Constants{2}{$Short}{"Value"};
12826 if(defined $Func_ShortName{2}{$Val})
12827 { # old name defined to new
12828 next;
12829 }
12830 }
12831 }
12832
12833 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012834 $RemovedInt{$Level}{$Symbol} = 1;
12835 if($Level eq "Source")
12836 { # search for a source-compatible equivalent
12837 setAlternative($Symbol, $Level);
12838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012839 }
12840 }
12841}
12842
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012843sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012845 my $Level = $_[0];
12846 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012847 { # checking added symbols
12848 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012849 next if($CompleteSignature{2}{$Symbol}{"Private"});
12850 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012851 if($Level eq "Binary")
12852 {
12853 if($CompleteSignature{2}{$Symbol}{"InLine"})
12854 {
12855 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12856 { # skip inline non-virtual functions
12857 next;
12858 }
12859 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012860 }
12861 else
12862 { # Source
12863 if($SourceAlternative_B{$Symbol}) {
12864 next;
12865 }
12866 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012867 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870 { # checking removed symbols
12871 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012872 next if($CompleteSignature{1}{$Symbol}{"Private"});
12873 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012874 if($Level eq "Binary")
12875 {
12876 if($CompleteSignature{1}{$Symbol}{"InLine"})
12877 {
12878 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12879 { # skip inline non-virtual functions
12880 next;
12881 }
12882 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012883 }
12884 else
12885 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012886 if(my $Alt = $SourceAlternative{$Symbol})
12887 {
12888 if(defined $CompleteSignature{1}{$Alt}
12889 and $CompleteSignature{1}{$Symbol}{"Const"})
12890 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012891 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012892 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012893 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012894 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012895 }
12896 else
12897 { # do NOT show removed symbol
12898 next;
12899 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012900 }
12901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012902 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012903 }
12904}
12905
12906sub addParamNames($)
12907{
12908 my $LibraryVersion = $_[0];
12909 return if(not keys(%AddIntParams));
12910 my $SecondVersion = $LibraryVersion==1?2:1;
12911 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12912 {
12913 next if(not keys(%{$AddIntParams{$Interface}}));
12914 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012915 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012916 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12917 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012918 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012919 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12920 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12921 {
12922 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12923 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12924 }
12925 }
12926 else {
12927 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12928 }
12929 }
12930 }
12931 }
12932}
12933
12934sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012935{ # detect changed typedefs to show
12936 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012937 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12938 {
12939 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012940 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12941 if(not $BName1 or isAnon($BName1)) {
12942 next;
12943 }
12944 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12945 if(not $BName2 or isAnon($BName2)) {
12946 next;
12947 }
12948 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012949 $ChangedTypedef{$Typedef} = 1;
12950 }
12951 }
12952}
12953
12954sub get_symbol_suffix($$)
12955{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012956 my ($Symbol, $Full) = @_;
12957 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012958 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012959 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012960 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012961 if(not $Full) {
12962 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12963 }
12964 return $Suffix;
12965}
12966
12967sub get_symbol_prefix($$)
12968{
12969 my ($Symbol, $LibVersion) = @_;
12970 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12971 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12972 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012973 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012974 }
12975 return $ShortName;
12976}
12977
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012978sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012979{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012980 my $Symbol = $_[0];
12981 my $PSymbol = $Symbol;
12982 if(not defined $CompleteSignature{2}{$PSymbol}
12983 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12984 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12985 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012986 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012987 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012988 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012989 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012990 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12991 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012992 {
12993 if(defined $CompleteSignature{2}{$PSymbol}
12994 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12995 {
12996 $SourceAlternative{$Symbol} = $PSymbol;
12997 $SourceAlternative_B{$PSymbol} = $Symbol;
12998 if(not defined $CompleteSignature{1}{$PSymbol}
12999 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13000 $SourceReplacement{$Symbol} = $PSymbol;
13001 }
13002 }
13003 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013004 }
13005 else
13006 {
13007 foreach my $Sp ("KV", "VK", "K", "V")
13008 {
13009 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13010 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13011 {
13012 if(defined $CompleteSignature{2}{$PSymbol}
13013 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13014 {
13015 $SourceAlternative{$Symbol} = $PSymbol;
13016 $SourceAlternative_B{$PSymbol} = $Symbol;
13017 if(not defined $CompleteSignature{1}{$PSymbol}
13018 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13019 $SourceReplacement{$Symbol} = $PSymbol;
13020 }
13021 }
13022 }
13023 $PSymbol = $Symbol;
13024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013025 }
13026 }
13027 }
13028 return "";
13029}
13030
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013031sub getSymKind($$)
13032{
13033 my ($Symbol, $LibVersion) = @_;
13034 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13035 {
13036 return "Global_Data";
13037 }
13038 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13039 {
13040 return "Method";
13041 }
13042 return "Function";
13043}
13044
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013045sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013046{
13047 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013048 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013049
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013050 mergeBases($Level);
13051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013052 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013053 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013054 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013055 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013056 next;
13057 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013058 if(defined $CompleteSignature{1}{$Symbol}
13059 and $CompleteSignature{1}{$Symbol}{"Header"})
13060 { # double-check added symbol
13061 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013062 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013063 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013064 next;
13065 }
13066 if($Symbol=~/\A(_Z|\?)/)
13067 { # C++
13068 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13069 }
13070 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13071 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013072 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13073 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013074 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013075 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013076 {
13077 if($TName_Tid{1}{$AffectedClass_Name})
13078 { # class should exist in previous version
13079 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13080 { # old v-table is NOT copied by old applications
13081 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13082 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013083 "Target"=>get_Signature($Symbol, 2),
13084 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013085 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013087 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013088 }
13089 }
13090 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013091 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13092 { # check all removed exported symbols
13093 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013094 next;
13095 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013096 if(defined $CompleteSignature{2}{$Symbol}
13097 and $CompleteSignature{2}{$Symbol}{"Header"})
13098 { # double-check removed symbol
13099 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013100 }
13101 if($CompleteSignature{1}{$Symbol}{"Private"})
13102 { # skip private methods
13103 next;
13104 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013105 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013106 next;
13107 }
13108 $CheckedSymbols{$Level}{$Symbol} = 1;
13109 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13110 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013111 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13112 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013113 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013114 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13115 {
13116 if($TName_Tid{2}{$AffectedClass_Name})
13117 { # class should exist in newer version
13118 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13119 { # old v-table is NOT copied by old applications
13120 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13121 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013122 "Target"=>get_Signature($OverriddenMethod, 1),
13123 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013124 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013127 }
13128 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013129 if($Level eq "Binary"
13130 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013131 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013132 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013133 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013134 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013136 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013137 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013138 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013139 {
13140 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13141 "Target"=>$tr_name{$Symbol},
13142 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013143 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013144 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013145 else
13146 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013147 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013148 "Target"=>$tr_name{$Symbol},
13149 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013150 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013151 }
13152 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013153 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013154 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013155 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156 {
13157 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13158 "Target"=>$tr_name{$Symbol},
13159 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013160 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013161 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013162 else
13163 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013164 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013165 "Target"=>$tr_name{$Symbol},
13166 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013167 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 }
13169 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013170 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13171 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13172 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13173 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13174 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013175 {
13176 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013177 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013178 $ProblemType = "Global_Data_Symbol_Changed_Type";
13179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013180 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13181 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013182 "Old_Type"=>$RTName1,
13183 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013184 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013185 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013186 }
13187 }
13188 }
13189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013190 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013193 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013194 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013195 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013196 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013197 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13198 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013199 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013200 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013201 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013202 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013203 }
13204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013205 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13206 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013207 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013208 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013209 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013210 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013211 }
13212 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013213 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013214 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013215 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013216 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013217 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013218 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013219 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013220 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013221 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013222 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013223 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013224 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013225 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013226 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013227 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013228 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013229 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013230 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013231 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013232 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013233 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013234 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013237 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 { # "volatile" to non-"volatile"
13239
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013240 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013241 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013242 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013243 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013244 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013245 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013246 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013247 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013248 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013249 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013250 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013251 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013252 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013253 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013254 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013255 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013257 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13258 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013259 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013260 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013261 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 }
13263 }
13264 }
13265 }
13266 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013267 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13268 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013269 $CurrentSymbol = $Symbol;
13270
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013271 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13272 if($Level eq "Source")
13273 { # remove symbol version
13274 $Symbol=$SN;
13275 }
13276 else
13277 { # Binary
13278 if(not $SV)
13279 { # symbol without version
13280 if(my $VSym = $SymVer{1}{$Symbol})
13281 { # the symbol is linked with versioned symbol
13282 if($CompleteSignature{2}{$VSym}{"MnglName"})
13283 { # show report for symbol@ver only
13284 next;
13285 }
13286 elsif(not link_symbol($VSym, 2, "-Deps"))
13287 { # changed version: sym@v1 to sym@v2
13288 # do NOT show report for symbol
13289 next;
13290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013291 }
13292 }
13293 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 my $PSymbol = $Symbol;
13295 if($Level eq "Source"
13296 and my $S = $SourceReplacement{$Symbol})
13297 { # take a source-compatible replacement function
13298 $PSymbol = $S;
13299 }
13300 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013301 { # private symbols
13302 next;
13303 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013304 if(not defined $CompleteSignature{1}{$Symbol}
13305 or not defined $CompleteSignature{2}{$PSymbol})
13306 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 next;
13308 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013309 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13310 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13311 { # no mangled name
13312 next;
13313 }
13314 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13315 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013316 { # without a header
13317 next;
13318 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013319
13320 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13321 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13322 { # became pure
13323 next;
13324 }
13325 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13326 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13327 { # became non-pure
13328 next;
13329 }
13330
13331 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13332 { # exported, target, inline virtual and pure virtual
13333 next;
13334 }
13335 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13336 { # exported, target, inline virtual and pure virtual
13337 next;
13338 }
13339
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013340 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013341 {
13342 if($CompleteSignature{1}{$Symbol}{"Data"}
13343 and $CompleteSignature{2}{$PSymbol}{"Data"})
13344 {
13345 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13346 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13347 if(defined $Value1)
13348 {
13349 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13350 if(defined $Value2)
13351 {
13352 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13353 if($Value1 ne $Value2)
13354 {
13355 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13356 "Old_Value"=>$Value1,
13357 "New_Value"=>$Value2,
13358 "Target"=>get_Signature($Symbol, 1) );
13359 }
13360 }
13361 }
13362 }
13363 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013364
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013365 if($CompleteSignature{2}{$PSymbol}{"Private"})
13366 {
13367 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13368 "Target"=>get_Signature_M($PSymbol, 2) );
13369 }
13370 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13371 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13372 {
13373 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13374 "Target"=>get_Signature_M($PSymbol, 2) );
13375 }
13376 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13377 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13378 {
13379 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13380 "Target"=>get_Signature_M($PSymbol, 2) );
13381 }
13382
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013383 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013384 mergeVirtualTables($Symbol, $Level);
13385
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013386 if($COMPILE_ERRORS)
13387 { # if some errors occurred at the compiling stage
13388 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013390 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 { # missed information about parameters in newer version
13392 next;
13393 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013394 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013396 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013397 next;
13398 }
13399 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013400 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013401 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013403 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13404 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13406 "Target"=>get_Signature($Symbol, 1)
13407 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013409 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013410 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13411 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013412 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013413 "Target"=>get_Signature($Symbol, 1)
13414 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013415 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13417 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013420 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013421 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13422 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13423 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013425 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013426 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13427 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013428 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013429 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013430 my $ProblemType = "Virtual_Method_Position";
13431 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13432 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013434 if(isUsedClass($Class_Id, 1, $Level))
13435 {
13436 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013437 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013438 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013439 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13440 next;
13441 }
13442 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013443 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013444 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13445 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013446 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013447 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013448 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013450 }
13451 }
13452 }
13453 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013454 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13455 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013456 { # do NOT check type changes in pure virtuals
13457 next;
13458 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013459 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013460 if($Symbol=~/\A(_Z|\?)/
13461 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013462 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013463 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013464 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013465 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013466 }
13467 }
13468 else
13469 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013470 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013472 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013473 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13474 last if($PType2_Name eq "...");
13475 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13476 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013477 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013478 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013479 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013480 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13481 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013482 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13483 $ParamPos_Prev = "lost";
13484 }
13485 }
13486 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013487 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013488 }
13489 if($ParamPos_Prev eq "lost")
13490 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013491 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013492 {
13493 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013494 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013495 $ProblemType = "Added_Unnamed_Parameter";
13496 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013497 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013498 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013499 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013500 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013502 }
13503 else
13504 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013505 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013506 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013507 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013508 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13509 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013510 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013511 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013512 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013513 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013514 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013515 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013516 "Param_Type"=>$PType2_Name,
13517 "Old_Value"=>$PName_Old,
13518 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013519 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 }
13521 }
13522 else
13523 {
13524 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013525 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013526 $ProblemType = "Added_Middle_Unnamed_Parameter";
13527 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013528 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013529 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013530 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013531 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013532 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013533 }
13534 }
13535 }
13536 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013537 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013538 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013539 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013540 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013541 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013543 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013544 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013545 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013546 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13547 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013548 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013549 }
13550 }
13551 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013552 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013554 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013555 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13556 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013557 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13558 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013559 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013560 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013562 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13563 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13565 $ParamPos_New = "lost";
13566 }
13567 }
13568 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013569 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013570 }
13571 if($ParamPos_New eq "lost")
13572 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013574 {
13575 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013576 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013577 $ProblemType = "Removed_Unnamed_Parameter";
13578 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013579 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013580 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013581 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013582 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013585 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013586 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013587 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013588 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013589 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013590 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013591 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013592 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013593 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013594 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013595 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013596 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013597 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013598 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013599 "Old_Value"=>$PName,
13600 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013601 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013602 }
13603 }
13604 else
13605 {
13606 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013607 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13609 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013610 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013611 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013612 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013613 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013614 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013615 }
13616 }
13617 }
13618 }
13619 }
13620 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013621 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13622 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013623 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013624
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013625 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013626 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013627 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13628 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013629 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013630
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013631 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013632 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013633 if($SubProblemType eq "Return_Type_And_Size") {
13634 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13635 }
13636 elsif($SubProblemType eq "Return_Type_Format") {
13637 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13638 }
13639 else {
13640 $ProblemTypes{"Global_Data_Type"} = 1;
13641 }
13642
13643 # quals
13644 if($SubProblemType eq "Return_Type"
13645 or $SubProblemType eq "Return_Type_And_Size"
13646 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013647 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013648 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13649 { # const to non-const
13650 if($RR==2) {
13651 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13652 }
13653 else {
13654 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13655 }
13656 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013658 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13659 { # non-const to const
13660 if($RA==2) {
13661 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13662 }
13663 else {
13664 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13665 }
13666 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 }
13668 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013669 }
13670 else
13671 {
13672 # quals
13673 if($SubProblemType eq "Return_Type"
13674 or $SubProblemType eq "Return_Type_And_Size"
13675 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013677 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013678 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013679 if(addedQual($Old_Value, $New_Value, "volatile"))
13680 {
13681 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13682 if($Level ne "Source"
13683 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13684 $ProblemTypes{"Return_Type"} = 1;
13685 }
13686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013687 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013688 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13689 {
13690 if($RA==2) {
13691 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13692 }
13693 else {
13694 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13695 }
13696 if($Level ne "Source"
13697 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13698 $ProblemTypes{"Return_Type"} = 1;
13699 }
13700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013701 }
13702 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013703 if($Level eq "Binary"
13704 and not $CompleteSignature{1}{$Symbol}{"Data"})
13705 {
13706 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13707 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13708 { # if one of the architectures is unknown
13709 # then set other arhitecture to unknown too
13710 ($Arch1, $Arch2) = ("unknown", "unknown");
13711 }
13712 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013713 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013714 {
13715 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13716 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13717 }
13718 else
13719 {
13720 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13721 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13722 }
13723
13724 if($SubProblemType eq "Return_Type_Became_Void")
13725 {
13726 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13727 { # parameters stack has been affected
13728 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013729 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013730 }
13731 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013732 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013733 }
13734 }
13735 }
13736 elsif($SubProblemType eq "Return_Type_From_Void")
13737 {
13738 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13739 { # parameters stack has been affected
13740 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013741 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013742 }
13743 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013744 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013745 }
13746 }
13747 }
13748 elsif($SubProblemType eq "Return_Type"
13749 or $SubProblemType eq "Return_Type_And_Size"
13750 or $SubProblemType eq "Return_Type_Format")
13751 {
13752 if($Conv1{"Method"} ne $Conv2{"Method"})
13753 {
13754 if($Conv1{"Method"} eq "stack")
13755 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013756 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013757 }
13758 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013759 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013760 }
13761 }
13762 else
13763 {
13764 if($Conv1{"Method"} eq "reg")
13765 {
13766 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13767 {
13768 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013769 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013770 }
13771 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013772 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013773 }
13774 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013775 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013776 }
13777 }
13778 }
13779 }
13780 }
13781 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013782
13783 if(not keys(%ProblemTypes))
13784 { # default
13785 $ProblemTypes{$SubProblemType} = 1;
13786 }
13787
13788 foreach my $ProblemType (keys(%ProblemTypes))
13789 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013790 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013792 }
13793 if($ReturnType1_Id and $ReturnType2_Id)
13794 {
13795 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013796 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13797
13798 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013799
13800 if($CompleteSignature{1}{$Symbol}{"Data"})
13801 {
13802 if($Level eq "Binary")
13803 {
13804 if(get_PLevel($ReturnType1_Id, 1)==0)
13805 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013806 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013807 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013808
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013809 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13810 {
13811 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013812 {
13813 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13814 {
13815 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13816 last;
13817 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013818 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013819 }
13820 }
13821 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013822 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013823 {
13824 if(defined $GlobalDataObject{1}{$Symbol}
13825 and defined $GlobalDataObject{2}{$Symbol})
13826 {
13827 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13828 my $New_Size = $GlobalDataObject{2}{$Symbol};
13829 if($Old_Size!=$New_Size)
13830 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013831 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013832 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013833 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013834 }
13835 }
13836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013837 }
13838 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013839
13840 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013841 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013842 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013843 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013844 my $NewLocation = "retval";
13845 if($SubLocation and $SubLocation ne "retval") {
13846 $NewLocation = "retval->".$SubLocation;
13847 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013848 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13849 }
13850 }
13851
13852 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13853 {
13854 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13855 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013856 my $NewLocation = "retval";
13857 if($SubLocation and $SubLocation ne "retval") {
13858 $NewLocation = "retval->".$SubLocation;
13859 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013860 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013861 }
13862 }
13863 }
13864
13865 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013866 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13867 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13868 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013869 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013870 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013871 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13872 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013873 if($ThisPtr1_Id and $ThisPtr2_Id)
13874 {
13875 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013876 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13877 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013878 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013879 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013880 {
13881 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013882 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013883 }
13884 }
13885 }
13886 }
13887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013888 if($Level eq "Binary") {
13889 mergeVTables($Level);
13890 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013891 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13892 $CheckedSymbols{$Level}{$Symbol} = 1;
13893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013894}
13895
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013896sub rmQuals($$)
13897{
13898 my ($Value, $Qual) = @_;
13899 if(not $Qual) {
13900 return $Value;
13901 }
13902 if($Qual eq "all")
13903 { # all quals
13904 $Qual = "const|volatile|restrict";
13905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013906 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013907 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013908 }
13909 return $Value;
13910}
13911
13912sub cmpBTypes($$$$)
13913{
13914 my ($T1, $T2, $V1, $V2) = @_;
13915 $T1 = uncover_typedefs($T1, $V1);
13916 $T2 = uncover_typedefs($T2, $V2);
13917 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13918}
13919
13920sub addedQual($$$)
13921{
13922 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013923 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013924}
13925
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013926sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013927{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013928 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013929 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013930}
13931
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013932sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013933{
13934 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13935 $Old_Value = uncover_typedefs($Old_Value, $V1);
13936 $New_Value = uncover_typedefs($New_Value, $V2);
13937 if($Old_Value eq $New_Value)
13938 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013939 return 0;
13940 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013941 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013942 { # without a qual
13943 return 0;
13944 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013945 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013946 { # became non-qual
13947 return 1;
13948 }
13949 else
13950 {
13951 my @BQ1 = getQualModel($Old_Value, $Qual);
13952 my @BQ2 = getQualModel($New_Value, $Qual);
13953 foreach (0 .. $#BQ1)
13954 { # removed qual
13955 if($BQ1[$_]==1
13956 and $BQ2[$_]!=1)
13957 {
13958 return 2;
13959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013960 }
13961 }
13962 return 0;
13963}
13964
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013965sub getQualModel($$)
13966{
13967 my ($Value, $Qual) = @_;
13968 if(not $Qual) {
13969 return $Value;
13970 }
13971
13972 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013973 while($Value=~/(\w+)/ and $1 ne $Qual) {
13974 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013975 }
13976 $Value=~s/[^\*\&\w]+//g;
13977
13978 # modeling
13979 # int*const*const == 011
13980 # int**const == 001
13981 my @Model = ();
13982 my @Elems = split(/[\*\&]/, $Value);
13983 if(not @Elems) {
13984 return (0);
13985 }
13986 foreach (@Elems)
13987 {
13988 if($_ eq $Qual) {
13989 push(@Model, 1);
13990 }
13991 else {
13992 push(@Model, 0);
13993 }
13994 }
13995
13996 return @Model;
13997}
13998
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013999my %StringTypes = map {$_=>1} (
14000 "char*",
14001 "char const*"
14002);
14003
14004my %CharTypes = map {$_=>1} (
14005 "char",
14006 "char const"
14007);
14008
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014009sub showVal($$$)
14010{
14011 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014012 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014013 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014014 if(substr($Value, 0, 2) eq "_Z")
14015 {
14016 if(my $Unmangled = $tr_name{$Value}) {
14017 return $Unmangled;
14018 }
14019 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014020 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014021 { # strings
14022 return "\"$Value\"";
14023 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014024 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014025 { # characters
14026 return "\'$Value\'";
14027 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014028 if($Value eq "")
14029 { # other
14030 return "\'\'";
14031 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014032 return $Value;
14033}
14034
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014035sub getRegs($$$)
14036{
14037 my ($LibVersion, $Symbol, $Pos) = @_;
14038
14039 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14040 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014041 my %Regs = ();
14042 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14043 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014044 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014045 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14046 }
14047 }
14048
14049 return join(", ", sort keys(%Regs));
14050 }
14051
14052 return undef;
14053}
14054
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014055sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014056{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014057 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014058 if(not $Symbol) {
14059 return;
14060 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014061 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14062 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14063 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14064 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014065 if(not $PType1_Id
14066 or not $PType2_Id) {
14067 return;
14068 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014069
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014070 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014071 { # do not merge "this"
14072 if($PName1 eq "this" or $PName2 eq "this") {
14073 return;
14074 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014075 }
14076
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014077 my %Type1 = get_Type($PType1_Id, 1);
14078 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014079
14080 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14081
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014082 my %BaseType1 = get_BaseType($PType1_Id, 1);
14083 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014084
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014085 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014086
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014087 if($Level eq "Binary")
14088 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014089 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014090 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14091 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14092 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14093 {
14094 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014095 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014096 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014097 }
14098 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14099 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14100 {
14101 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014102 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014103 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014105 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014106
14107 if(defined $UsedDump{1}{"DWARF"}
14108 and defined $UsedDump{2}{"DWARF"})
14109 {
14110 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14111 {
14112 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14113 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14114 if($Old_Regs and $New_Regs)
14115 {
14116 if($Old_Regs ne $New_Regs)
14117 {
14118 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14119 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014120 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014121 "Old_Value"=>$Old_Regs,
14122 "New_Value"=>$New_Regs );
14123 }
14124 }
14125 elsif($Old_Regs and not $New_Regs)
14126 {
14127 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14128 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014129 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014130 "Old_Value"=>$Old_Regs );
14131 }
14132 elsif(not $Old_Regs and $New_Regs)
14133 {
14134 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14135 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014136 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014137 "New_Value"=>$New_Regs );
14138 }
14139 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14140 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14141 {
14142 if($Old_Offset ne $New_Offset)
14143 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014144 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14145 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14146
14147 $Old_Offset = $Old_Offset - $Start1;
14148 $New_Offset = $New_Offset - $Start2;
14149
14150 if($Old_Offset ne $New_Offset)
14151 {
14152 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14153 "Target"=>$PName1,
14154 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14155 "Old_Value"=>$Old_Offset,
14156 "New_Value"=>$New_Offset );
14157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014158 }
14159 }
14160 }
14161 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014162 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014163 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14164 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014165 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014166 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014167 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14168 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014169 if(not checkDump(1, "2.13")
14170 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014171 { # support for old ABI dumps
14172 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014173 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014174 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014175 and $Value_Old eq "false" and $Value_New eq "0")
14176 { # int class::method ( bool p = 0 );
14177 # old ABI dumps: "false"
14178 # new ABI dumps: "0"
14179 $Value_Old = "0";
14180 }
14181 }
14182 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014183 if(not checkDump(1, "2.18")
14184 and checkDump(2, "2.18"))
14185 { # support for old ABI dumps
14186 if(not defined $Value_Old
14187 and substr($Value_New, 0, 2) eq "_Z") {
14188 $Value_Old = $Value_New;
14189 }
14190 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014191 if(defined $Value_Old)
14192 {
14193 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14194 if(defined $Value_New)
14195 {
14196 $Value_New = showVal($Value_New, $PType2_Id, 2);
14197 if($Value_Old ne $Value_New)
14198 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014199 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014200 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014201 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014202 "Old_Value"=>$Value_Old,
14203 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014204 }
14205 }
14206 else
14207 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014208 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014209 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014210 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014211 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014212 }
14213 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014214 elsif(defined $Value_New)
14215 {
14216 $Value_New = showVal($Value_New, $PType2_Id, 2);
14217 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14218 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014219 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014220 "New_Value"=>$Value_New );
14221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014222 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014223
14224 if($ChkRnmd)
14225 {
14226 if($PName1 and $PName2 and $PName1 ne $PName2
14227 and $PType1_Id!=-1 and $PType2_Id!=-1
14228 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14229 { # except unnamed "..." value list (Id=-1)
14230 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14231 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014232 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014233 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14234 "Old_Value"=>$PName1,
14235 "New_Value"=>$PName2,
14236 "New_Signature"=>get_Signature($Symbol, 2) );
14237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014238 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014239
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014240 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014241 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014243 foreach my $SubProblemType (keys(%SubProblems))
14244 { # add new problems, remove false alarms
14245 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14246 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014247
14248 # quals
14249 if($SubProblemType eq "Parameter_Type"
14250 or $SubProblemType eq "Parameter_Type_And_Size"
14251 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014252 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014253 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014254 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014255 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014256 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014257 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014258 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14259 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14260 }
14261 }
14262 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14263 {
14264 if(removedQual($Old_Value, $New_Value, "volatile")) {
14265 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014266 }
14267 }
14268 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14269 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14270 { # int to "int const"
14271 delete($SubProblems{$SubProblemType});
14272 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014273 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014274 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14275 { # "int const" to int
14276 delete($SubProblems{$SubProblemType});
14277 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014278 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14279 { # "const" to non-"const"
14280 if($RR==2) {
14281 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14282 }
14283 else {
14284 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14285 }
14286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014287 }
14288 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014289
14290 if($Level eq "Source")
14291 {
14292 foreach my $SubProblemType (keys(%SubProblems))
14293 {
14294 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14295 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14296
14297 if($SubProblemType eq "Parameter_Type")
14298 {
14299 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14300 delete($SubProblems{$SubProblemType});
14301 }
14302 }
14303 }
14304 }
14305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014306 foreach my $SubProblemType (keys(%SubProblems))
14307 { # modify/register problems
14308 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14309 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014310 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14311 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014312
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014313 my $NewProblemType = $SubProblemType;
14314 if($Old_Value eq "..." and $New_Value ne "...")
14315 { # change from "..." to "int"
14316 if($ParamPos1==0)
14317 { # ISO C requires a named argument before "..."
14318 next;
14319 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014320 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014321 }
14322 elsif($New_Value eq "..." and $Old_Value ne "...")
14323 { # change from "int" to "..."
14324 if($ParamPos2==0)
14325 { # ISO C requires a named argument before "..."
14326 next;
14327 }
14328 $NewProblemType = "Parameter_Became_VaList";
14329 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014330 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014331 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014332 {
14333 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014334 if($Arch1 eq "unknown"
14335 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014337 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014338 ($Arch1, $Arch2) = ("unknown", "unknown");
14339 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014340 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014341 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014342 { # real
14343 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14344 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14345 }
14346 else
14347 { # model
14348 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14349 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14350 }
14351 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014352 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014353 if($Conv1{"Method"} eq "stack")
14354 {
14355 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14356 $NewProblemType = "Parameter_Type_And_Stack";
14357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014358 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014359 elsif($Conv1{"Method"} eq "reg")
14360 {
14361 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14362 $NewProblemType = "Parameter_Type_And_Register";
14363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014364 }
14365 }
14366 else
14367 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014368 if($Conv1{"Method"} eq "stack") {
14369 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014370 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014371 elsif($Conv1{"Method"} eq "register") {
14372 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014373 }
14374 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014375 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14376 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014377 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014378 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014379 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014380 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014381 "New_Signature"=>get_Signature($Symbol, 2) );
14382 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014383 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014384
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014385 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014387 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014388 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14389 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014390 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014391 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014392 {
14393 my $NewProblemType = $SubProblemType;
14394 if($SubProblemType eq "DataType_Size")
14395 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014396 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014397 { # stack has been affected
14398 $NewProblemType = "DataType_Size_And_Stack";
14399 }
14400 }
14401 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014402 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014403 }
14404 }
14405}
14406
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014407sub find_ParamPair_Pos_byName($$$)
14408{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014409 my ($Name, $Symbol, $LibVersion) = @_;
14410 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014412 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14413 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 {
14415 return $ParamPos;
14416 }
14417 }
14418 return "lost";
14419}
14420
14421sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14422{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014423 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014424 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014425 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014426 {
14427 next if($Order eq "backward" and $ParamPos>$MediumPos);
14428 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014429 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14430 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014431 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014432 push(@Positions, $ParamPos);
14433 }
14434 }
14435 return @Positions;
14436}
14437
14438sub getTypeIdByName($$)
14439{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014440 my ($TypeName, $LibVersion) = @_;
14441 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014442}
14443
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014444sub diffTypes($$$)
14445{
14446 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14447 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14448 }
14449 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14450 { # skip recursive declarations
14451 return 0;
14452 }
14453
14454 pushType($_[0], $_[1], \@RecurTypes_Diff);
14455 my $Diff = diffTypes_I(@_);
14456 pop(@RecurTypes_Diff);
14457
14458 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14459}
14460
14461sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014462{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014463 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014464
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014465 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14466 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14469 { # equal types
14470 return 0;
14471 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014472 if($Type1_Pure{"Name"} eq "void")
14473 { # from void* to something
14474 return 0;
14475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 if($Type1_Pure{"Name"}=~/\*/
14477 or $Type2_Pure{"Name"}=~/\*/)
14478 { # compared in detectTypeChange()
14479 return 0;
14480 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014481
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014482 my %FloatType = map {$_=>1} (
14483 "float",
14484 "double",
14485 "long double"
14486 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014487
14488 my $T1 = $Type1_Pure{"Type"};
14489 my $T2 = $Type2_Pure{"Type"};
14490
14491 if($T1 eq "Struct"
14492 and $T2 eq "Class")
14493 { # compare as data structures
14494 $T2 = "Struct";
14495 }
14496
14497 if($T1 eq "Class"
14498 and $T2 eq "Struct")
14499 { # compare as data structures
14500 $T1 = "Struct";
14501 }
14502
14503 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014504 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014505 if($T1 eq "Intrinsic"
14506 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014507 { # "int" to "enum"
14508 return 0;
14509 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014510 elsif($T2 eq "Intrinsic"
14511 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 { # "enum" to "int"
14513 return 0;
14514 }
14515 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014516 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014517 # ...
14518 return 1;
14519 }
14520 }
14521 else
14522 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014523 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014524 {
14525 if($FloatType{$Type1_Pure{"Name"}}
14526 or $FloatType{$Type2_Pure{"Name"}})
14527 { # "float" to "double"
14528 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014529 if($Level eq "Source")
14530 { # Safe
14531 return 0;
14532 }
14533 else {
14534 return 1;
14535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 }
14537 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014538 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014539 {
14540 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14541 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014542 if(not @Membs1
14543 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014544 { # private
14545 return 0;
14546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014547 if($#Membs1!=$#Membs2)
14548 { # different number of elements
14549 return 1;
14550 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014551 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 {
14553 foreach my $Pos (@Membs1)
14554 { # compare elements by name and value
14555 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14556 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14557 { # different names
14558 return 1;
14559 }
14560 }
14561 }
14562 else
14563 {
14564 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014566 if($Level eq "Source")
14567 {
14568 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14569 { # different names
14570 return 1;
14571 }
14572 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014573
14574 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14575 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14576
14577 if($MT1{"Name"} ne $MT2{"Name"}
14578 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14579 {
14580 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14581 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14582
14583 if($PL1 ne $PL2)
14584 { # different pointer level
14585 return 1;
14586 }
14587
14588 # compare base types
14589 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14590 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14591
14592 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14593 { # different types
14594 return 1;
14595 }
14596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014597 }
14598 }
14599 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014600 else
14601 {
14602 # TODO: arrays, etc.
14603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014604 }
14605 return 0;
14606}
14607
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014608sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014609{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014610 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014611 if(not $Type1_Id or not $Type2_Id) {
14612 return ();
14613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014614 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014615 my %Type1 = get_Type($Type1_Id, 1);
14616 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014617 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14618 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14619 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14620 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 +040014621
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014622 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14623 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014624 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14625 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14626 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14627 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14628 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14629 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14630 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014631 if($Type1{"Name"} eq $Type2{"Name"})
14632 {
14633 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14634 { # will be reported in mergeTypes() as typedef problem
14635 return ();
14636 }
14637 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14638 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14639 if(%Typedef_1 and %Typedef_2)
14640 {
14641 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14642 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14643 { # const Typedef
14644 return ();
14645 }
14646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014647 }
14648 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14649 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014650 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014651 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14652 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014653 {
14654 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14655 "Old_Value"=>$Type1_Base{"Name"},
14656 "New_Value"=>$Type2_Base{"Name"},
14657 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014658 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014659 }
14660 else
14661 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014662 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014663 { # format change
14664 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14665 "Old_Value"=>$Type1_Base{"Name"},
14666 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014667 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014668 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014669 }
14670 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14671 {
14672 %{$LocalProblems{$Prefix."_BaseType"}}=(
14673 "Old_Value"=>$Type1_Base{"Name"},
14674 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014675 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014676 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014677 }
14678 }
14679 }
14680 }
14681 elsif($Type1{"Name"} ne $Type2{"Name"})
14682 { # type change
14683 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14684 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014685 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686 and $Type1_Pure{"Name"} eq "void")
14687 {
14688 %{$LocalProblems{"Return_Type_From_Void"}}=(
14689 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014690 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 elsif($Prefix eq "Return"
14693 and $Type2_Pure{"Name"} eq "void")
14694 {
14695 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14696 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014697 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014699 else
14700 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014701 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014702 and $Type1{"Size"} and $Type2{"Size"}
14703 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014704 {
14705 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14706 "Old_Value"=>$Type1{"Name"},
14707 "New_Value"=>$Type2{"Name"},
14708 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014709 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710 }
14711 else
14712 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014713 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014714 { # format change
14715 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14716 "Old_Value"=>$Type1{"Name"},
14717 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014718 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014719 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014720 }
14721 elsif(tNameLock($Type1_Id, $Type2_Id))
14722 { # FIXME: correct this condition
14723 %{$LocalProblems{$Prefix."_Type"}}=(
14724 "Old_Value"=>$Type1{"Name"},
14725 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014726 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014727 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014728 }
14729 }
14730 }
14731 }
14732 }
14733 if($Type1_PLevel!=$Type2_PLevel)
14734 {
14735 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14736 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14737 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014738 if($Level eq "Source")
14739 {
14740 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014741 "Old_Value"=>$Type1_PLevel,
14742 "New_Value"=>$Type2_PLevel);
14743 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014744 else
14745 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014746 if($Type2_PLevel>$Type1_PLevel)
14747 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014748 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14749 "Old_Value"=>$Type1_PLevel,
14750 "New_Value"=>$Type2_PLevel);
14751 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014752 else
14753 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014754 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14755 "Old_Value"=>$Type1_PLevel,
14756 "New_Value"=>$Type2_PLevel);
14757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014758 }
14759 }
14760 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014761 if($Type1_Pure{"Type"} eq "Array"
14762 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014763 { # base_type[N] -> base_type[N]
14764 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014765 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014766 foreach my $SubProblemType (keys(%SubProblems))
14767 {
14768 $SubProblemType=~s/_Type/_BaseType/g;
14769 next if(defined $LocalProblems{$SubProblemType});
14770 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14771 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14772 }
14773 }
14774 }
14775 return %LocalProblems;
14776}
14777
14778sub tNameLock($$)
14779{
14780 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014781 my $Changed = 0;
14782 if(differentDumps("G"))
14783 { # different GCC versions
14784 $Changed = 1;
14785 }
14786 elsif(differentDumps("V"))
14787 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014788 if(not checkDump(1, "2.20")
14789 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014790 { # latest names update
14791 # 2.6: added restrict qualifier
14792 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014793 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014794 $Changed = 1;
14795 }
14796 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014797
14798 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14799 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14800
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014801 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14802 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14803
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014804 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014805 { # different formats
14806 if($UseOldDumps)
14807 { # old dumps
14808 return 0;
14809 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014810
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014811 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014812 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014813 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014814 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014815 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014816 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014817 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014818 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014819 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14820 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14821 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822 { # equal base types
14823 return 0;
14824 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014825
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014826 if(not checkDump(1, "2.13")
14827 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014828 { # broken array names in ABI dumps < 2.13
14829 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014830 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014831 return 0;
14832 }
14833 }
14834
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014835 if(not checkDump(1, "2.6")
14836 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014837 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014838 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014839 and $TN2=~/\brestrict\b/) {
14840 return 0;
14841 }
14842 }
14843
14844 if(not checkDump(1, "2.20")
14845 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014846 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014847 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14848 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014849 return 0;
14850 }
14851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014852 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014853 else
14854 {
14855 # typedef struct {...} type_t
14856 # typedef struct type_t {...} type_t
14857 if(index($TN1, " ".$TN2)!=-1)
14858 {
14859 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14860 return 0;
14861 }
14862 }
14863 if(index($TN2, " ".$TN1)!=-1)
14864 {
14865 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14866 return 0;
14867 }
14868 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014869
14870 if($TT1 eq "FuncPtr"
14871 and $TT2 eq "FuncPtr")
14872 {
14873 my $TN1_C = $TN1;
14874 my $TN2_C = $TN2;
14875
14876 $TN1_C=~s/\b(struct|union) //g;
14877 $TN2_C=~s/\b(struct|union) //g;
14878
14879 if($TN1_C eq $TN2_C) {
14880 return 0;
14881 }
14882 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014883 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014884
14885 my ($N1, $N2) = ($TN1, $TN2);
14886 $N1=~s/\b(struct|union) //g;
14887 $N2=~s/\b(struct|union) //g;
14888
14889 if($N1 eq $N2)
14890 { # QList<struct QUrl> and QList<QUrl>
14891 return 0;
14892 }
14893
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014894 return 1;
14895}
14896
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014897sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014898{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014899 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014900 if(defined $Cache{"differentDumps"}{$Check}) {
14901 return $Cache{"differentDumps"}{$Check};
14902 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014903 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014904 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014905 if($Check eq "G")
14906 {
14907 if(getGccVersion(1) ne getGccVersion(2))
14908 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014909 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014910 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014911 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014912 if($Check eq "V")
14913 {
14914 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14915 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14916 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014917 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014918 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014921 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014922}
14923
14924sub formatVersion($$)
14925{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014926 my ($V, $Digits) = @_;
14927 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014928 return join(".", splice(@Elems, 0, $Digits));
14929}
14930
14931sub htmlSpecChars($)
14932{
14933 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014934 if(not $Str) {
14935 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14938 $Str=~s/</&lt;/g;
14939 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14940 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014941 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14942 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014943 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014944 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014945 $Str=~s/\n/<br\/>/g;
14946 $Str=~s/\"/&quot;/g;
14947 $Str=~s/\'/&#39;/g;
14948 return $Str;
14949}
14950
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014951sub xmlSpecChars($)
14952{
14953 my $Str = $_[0];
14954 if(not $Str) {
14955 return $Str;
14956 }
14957
14958 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14959 $Str=~s/</&lt;/g;
14960 $Str=~s/>/&gt;/g;
14961
14962 $Str=~s/\"/&quot;/g;
14963 $Str=~s/\'/&#39;/g;
14964
14965 return $Str;
14966}
14967
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014968sub xmlSpecChars_R($)
14969{
14970 my $Str = $_[0];
14971 if(not $Str) {
14972 return $Str;
14973 }
14974
14975 $Str=~s/&amp;/&/g;
14976 $Str=~s/&lt;/</g;
14977 $Str=~s/&gt;/>/g;
14978
14979 $Str=~s/&quot;/"/g;
14980 $Str=~s/&#39;/'/g;
14981
14982 return $Str;
14983}
14984
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014985sub black_name($)
14986{
14987 my $Name = $_[0];
14988 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14989}
14990
14991sub highLight_Signature($)
14992{
14993 my $Signature = $_[0];
14994 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14995}
14996
14997sub highLight_Signature_Italic_Color($)
14998{
14999 my $Signature = $_[0];
15000 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15001}
15002
15003sub separate_symbol($)
15004{
15005 my $Symbol = $_[0];
15006 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15007 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15008 ($Name, $Spec, $Ver) = ($1, $2, $3);
15009 }
15010 return ($Name, $Spec, $Ver);
15011}
15012
15013sub cut_f_attrs($)
15014{
15015 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15016 return $2;
15017 }
15018 return "";
15019}
15020
15021sub highLight_Signature_PPos_Italic($$$$$)
15022{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015023 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15024 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015025 if($CheckObjectsOnly) {
15026 $ItalicParams=$ColorParams=0;
15027 }
15028 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15029 my $Return = "";
15030 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15031 $Return = $2;
15032 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015033 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015034 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015035 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015036 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015037 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015038 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015040 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015041 }
15042 return $Signature;
15043 }
15044 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15045 $Begin.=" " if($Begin!~/ \Z/);
15046 $End = cut_f_attrs($Signature);
15047 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015048 my ($Short, $Params) = split_Signature($Signature);
15049 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015050 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015051 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015052 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015053 $Part=~s/\A\s+|\s+\Z//g;
15054 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15055 if($Part=~/\([\*]+(\w+)\)/i) {
15056 $ParamName = $1;#func-ptr
15057 }
15058 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15059 $ParamName = $1;
15060 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015061 if(not $ParamName)
15062 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015063 push(@Parts, $Part_Styled);
15064 next;
15065 }
15066 if($ItalicParams and not $TName_Tid{1}{$Part}
15067 and not $TName_Tid{2}{$Part})
15068 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015069 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015070 if($Param_Pos ne ""
15071 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015072 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015073 }
15074 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015075 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015076 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015077 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015078 }
15079 $Part_Styled=~s/,(\w)/, $1/g;
15080 push(@Parts, $Part_Styled);
15081 }
15082 if(@Parts)
15083 {
15084 foreach my $Num (0 .. $#Parts)
15085 {
15086 if($Num==$#Parts)
15087 { # add ")" to the last parameter
15088 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15089 }
15090 elsif(length($Parts[$Num])<=45) {
15091 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15092 }
15093 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015094 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015095 }
15096 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015097 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015098 }
15099 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015100 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015102 $Signature=~s!\[\]![&#160;]!g;
15103 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015104 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15105 if($SymbolVersion) {
15106 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15107 }
15108 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015109}
15110
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015111sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015112{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015113 my $Signature = $_[0];
15114 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15115 {
15116 $Signature=~s/\A\Q$ShortName\E\(//g;
15117 cut_f_attrs($Signature);
15118 $Signature=~s/\)\Z//;
15119 return ($ShortName, $Signature);
15120 }
15121
15122 # error
15123 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015124}
15125
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015126sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015127{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015128 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015129 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015130 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15131 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015132 foreach my $Pos (0 .. length($Params) - 1)
15133 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015134 my $S = substr($Params, $Pos, 1);
15135 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015136 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015137 }
15138 if($S eq "," and
15139 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015140 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015141 if($Comma)
15142 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015143 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015144 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015145 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015146 }
15147 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015148 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015149 }
15150 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015151 if(not $Sp)
15152 { # remove spaces
15153 foreach (@Parts)
15154 {
15155 s/\A //g;
15156 s/ \Z//g;
15157 }
15158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015159 return @Parts;
15160}
15161
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015162sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163{
15164 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015165 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015166 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015167 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15168 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015169 $Center+=length($1);
15170 }
15171 foreach my $Pos (0 .. length($Sign)-1)
15172 {
15173 my $S = substr($Sign, $Pos, 1);
15174 if($S eq $Target)
15175 {
15176 if($B{"("}==$B{")"}
15177 and $B{"<"}==$B{">"}) {
15178 return $Center;
15179 }
15180 }
15181 if(defined $B{$S}) {
15182 $B{$S}+=1;
15183 }
15184 $Center+=1;
15185 }
15186 return 0;
15187}
15188
15189sub appendFile($$)
15190{
15191 my ($Path, $Content) = @_;
15192 return if(not $Path);
15193 if(my $Dir = get_dirname($Path)) {
15194 mkpath($Dir);
15195 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015196 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 print FILE $Content;
15198 close(FILE);
15199}
15200
15201sub writeFile($$)
15202{
15203 my ($Path, $Content) = @_;
15204 return if(not $Path);
15205 if(my $Dir = get_dirname($Path)) {
15206 mkpath($Dir);
15207 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015208 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015209 print FILE $Content;
15210 close(FILE);
15211}
15212
15213sub readFile($)
15214{
15215 my $Path = $_[0];
15216 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015217 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015218 local $/ = undef;
15219 my $Content = <FILE>;
15220 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015221 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015222 $Content=~s/\r/\n/g;
15223 }
15224 return $Content;
15225}
15226
15227sub get_filename($)
15228{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015229 if(defined $Cache{"get_filename"}{$_[0]}) {
15230 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015232 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15233 return ($Cache{"get_filename"}{$_[0]}=$1);
15234 }
15235 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015236}
15237
15238sub get_dirname($)
15239{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015240 if(defined $Cache{"get_dirname"}{$_[0]}) {
15241 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015242 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015243 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15244 return ($Cache{"get_dirname"}{$_[0]}=$1);
15245 }
15246 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015247}
15248
15249sub separate_path($) {
15250 return (get_dirname($_[0]), get_filename($_[0]));
15251}
15252
15253sub esc($)
15254{
15255 my $Str = $_[0];
15256 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15257 return $Str;
15258}
15259
15260sub readLineNum($$)
15261{
15262 my ($Path, $Num) = @_;
15263 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015264 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265 foreach (1 ... $Num) {
15266 <FILE>;
15267 }
15268 my $Line = <FILE>;
15269 close(FILE);
15270 return $Line;
15271}
15272
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015273sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015274{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015275 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276 return () if(not $Path or not -f $Path);
15277 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015278 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15279 {
15280 foreach my $AttrVal (split(/;/, $1))
15281 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015282 if($AttrVal=~/(.+):(.+)/)
15283 {
15284 my ($Name, $Value) = ($1, $2);
15285 $Attributes{$Name} = $Value;
15286 }
15287 }
15288 }
15289 return \%Attributes;
15290}
15291
15292sub is_abs($) {
15293 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15294}
15295
15296sub get_abs_path($)
15297{ # abs_path() should NOT be called for absolute inputs
15298 # because it can change them
15299 my $Path = $_[0];
15300 if(not is_abs($Path)) {
15301 $Path = abs_path($Path);
15302 }
15303 return $Path;
15304}
15305
15306sub get_OSgroup()
15307{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015308 my $N = $Config{"osname"};
15309 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310 return "macos";
15311 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015312 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015313 return "bsd";
15314 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015315 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015316 return "beos";
15317 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015318 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015319 return "symbian";
15320 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015321 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322 return "windows";
15323 }
15324 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015325 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015326 }
15327}
15328
15329sub getGccVersion($)
15330{
15331 my $LibVersion = $_[0];
15332 if($GCC_VERSION{$LibVersion})
15333 { # dump version
15334 return $GCC_VERSION{$LibVersion};
15335 }
15336 elsif($UsedDump{$LibVersion}{"V"})
15337 { # old-version dumps
15338 return "unknown";
15339 }
15340 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15341 if(not $GccVersion) {
15342 return "unknown";
15343 }
15344 return $GccVersion;
15345}
15346
15347sub showArch($)
15348{
15349 my $Arch = $_[0];
15350 if($Arch eq "arm"
15351 or $Arch eq "mips") {
15352 return uc($Arch);
15353 }
15354 return $Arch;
15355}
15356
15357sub getArch($)
15358{
15359 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015360
15361 if($TargetArch) {
15362 return $TargetArch;
15363 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015364 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015365 { # dump version
15366 return $CPU_ARCH{$LibVersion};
15367 }
15368 elsif($UsedDump{$LibVersion}{"V"})
15369 { # old-version dumps
15370 return "unknown";
15371 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015372
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015373 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015374}
15375
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015376sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015377{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015378 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015380 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015381 if(getArch(1) ne getArch(2)
15382 or getArch(1) eq "unknown"
15383 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015384 { # don't show architecture in the header
15385 $ArchInfo="";
15386 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015387 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015388 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015389 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015390 }
15391 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015392 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015393 }
15394 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015395 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015396 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015397
15398 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15399 {
15400 my $M1 = $UsedDump{1}{"M"};
15401 my $M2 = $UsedDump{2}{"M"};
15402
15403 if($M1 eq $M2)
15404 {
15405 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15406 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15407 }
15408 else
15409 {
15410 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15411 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15412 }
15413 }
15414 else
15415 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015416 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015417 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15418 }
15419
15420 $Title .= $ArchInfo;
15421
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015422 if($AppPath) {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015423 $Title .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015424 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015425 $Title = "<h1>".$Title."</h1>\n";
15426 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015427}
15428
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015429sub get_CheckedHeaders($)
15430{
15431 my $LibVersion = $_[0];
15432
15433 my @Headers = ();
15434
15435 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15436 {
15437 my $File = get_filename($Path);
15438 if(not is_target_header($File, $LibVersion)) {
15439 next;
15440 }
15441
15442 if(skipHeader($File, $LibVersion)) {
15443 next;
15444 }
15445
15446 push(@Headers, $Path);
15447 }
15448
15449 return @Headers;
15450}
15451
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015452sub get_SourceInfo()
15453{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015454 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015455 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015456 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015457 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015458 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015459 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15460 $CheckedHeaders .= "<div class='h_list'>\n";
15461 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15462 {
15463 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15464 my $Name = get_filename($Identity);
15465 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15466 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15467 }
15468 $CheckedHeaders .= "</div>\n";
15469 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015470 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015471
15472 if(my @Sources = keys(%{$Registered_Sources{1}}))
15473 {
15474 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15475 $CheckedSources .= "<div class='h_list'>\n";
15476 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15477 {
15478 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15479 my $Name = get_filename($Identity);
15480 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15481 $CheckedSources .= $Name.$Comment."<br/>\n";
15482 }
15483 $CheckedSources .= "</div>\n";
15484 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015487 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015488 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015489 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015490 $CheckedLibs .= "<div class='lib_list'>\n";
15491 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15492 {
15493 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15494 $CheckedLibs .= $Library."<br/>\n";
15495 }
15496 $CheckedLibs .= "</div>\n";
15497 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015498 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015499 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15500}
15501
15502sub get_ObjTitle()
15503{
15504 if(defined $UsedDump{1}{"DWARF"}) {
15505 return "Objects";
15506 }
15507 else {
15508 return ucfirst($SLIB_TYPE)." Libraries";
15509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015510}
15511
15512sub get_TypeProblems_Count($$$)
15513{
15514 my ($TypeChanges, $TargetPriority, $Level) = @_;
15515 my $Type_Problems_Count = 0;
15516 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15517 {
15518 my %Kinds_Target = ();
15519 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15520 {
15521 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15522 {
15523 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015524 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15525 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015526 if($Kinds_Target{$Kind}{$Target}) {
15527 next;
15528 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015529
15530 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15531 {
15532 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15533 { # select a problem with the highest priority
15534 next;
15535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015536 }
15537 $Kinds_Target{$Kind}{$Target} = 1;
15538 $Type_Problems_Count += 1;
15539 }
15540 }
15541 }
15542 return $Type_Problems_Count;
15543}
15544
15545sub get_Summary($)
15546{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015547 my $Level = $_[0];
15548 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015549 $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 +040015550 %{$RESULT{$Level}} = (
15551 "Problems"=>0,
15552 "Warnings"=>0,
15553 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015554 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015555 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015556 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015557 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015558 {
15559 if(not defined $CompatRules{$Level}{$Kind})
15560 { # unknown rule
15561 if(not $UnknownRules{$Level}{$Kind})
15562 { # only one warning
15563 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15564 $UnknownRules{$Level}{$Kind}=1;
15565 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015566 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015567 }
15568 }
15569 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015570 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15571 {
15572 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15573 {
15574 if(not defined $CompatRules{$Level}{$Kind})
15575 { # unknown rule
15576 if(not $UnknownRules{$Level}{$Kind})
15577 { # only one warning
15578 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15579 $UnknownRules{$Level}{$Kind}=1;
15580 }
15581 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15582 }
15583 }
15584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015585 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015586 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015587 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015588 {
15589 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15590 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015591 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015592 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015593 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015594 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 $Added += 1;
15596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015597 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015598 {
15599 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015600 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015601 }
15602 else
15603 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015604 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015605 $I_Other += 1;
15606 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015607 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015608 $I_Problems_High += 1;
15609 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015610 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015611 $I_Problems_Medium += 1;
15612 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015613 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015614 $I_Problems_Low += 1;
15615 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015616 if(($Severity ne "Low" or $StrictCompat)
15617 and $Severity ne "Safe") {
15618 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619 }
15620 }
15621 }
15622 }
15623 }
15624 }
15625 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015626 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015628 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015629 {
15630 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15631 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015632 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015633 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015634 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15635 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015636 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015637 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15638
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015639 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015640 { # select a problem with the highest priority
15641 next;
15642 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015643
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015644 if(($Severity ne "Low" or $StrictCompat)
15645 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015646 {
15647 if(defined $TotalAffected{$Level}{$Interface})
15648 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015649 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15650 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015651 }
15652 }
15653 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015654 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015655 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015656 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015657
15658 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15659
15660 if($MaxSeverity)
15661 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015662 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15663 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015664 }
15665 }
15666 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015667 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015669 }
15670 }
15671 }
15672 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015673
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015674 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15675 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15676 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15677 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015678
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015679 %TypeChanges = (); # free memory
15680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 if($CheckObjectsOnly)
15682 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015683 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 }
15685 else
15686 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015687 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015688 if($ExtendedCheck)
15689 { # don't count external_func_0 for constants
15690 $SCount-=1;
15691 }
15692 if($SCount)
15693 {
15694 my %Weight = (
15695 "High" => 100,
15696 "Medium" => 50,
15697 "Low" => 25
15698 );
15699 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015700 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015701 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015702 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015703 }
15704 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015705 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015706 }
15707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015708 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15709 if($RESULT{$Level}{"Affected"}>=100) {
15710 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015711 }
15712
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015713 $RESULT{$Level}{"Problems"} += $Removed;
15714 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015715 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015716 if($StrictCompat) {
15717 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15718 }
15719 else {
15720 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015723 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015724 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015725 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015726 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015727 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015728 if($Severity eq "Safe")
15729 {
15730 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015731 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015732 elsif($Severity eq "Low")
15733 {
15734 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015735 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015736 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015737 }
15738
15739 if($C_Problems_Low)
15740 {
15741 if($StrictCompat) {
15742 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15743 }
15744 else {
15745 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015746 }
15747 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015748 if($RESULT{$Level}{"Problems"}
15749 and $RESULT{$Level}{"Affected"}) {
15750 $RESULT{$Level}{"Verdict"} = "incompatible";
15751 }
15752 else {
15753 $RESULT{$Level}{"Verdict"} = "compatible";
15754 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015755
15756 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15757 if(not $TotalTypes)
15758 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015759 $TotalTypes = keys(%{$TName_Tid{1}});
15760 }
15761
15762 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15763 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15764
15765 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15766
15767 if($ReportFormat eq "xml")
15768 { # XML
15769 # test info
15770 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15771 $TestInfo .= " <version1>\n";
15772 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015773 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15775 $TestInfo .= " </version1>\n";
15776
15777 $TestInfo .= " <version2>\n";
15778 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015779 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15781 $TestInfo .= " </version2>\n";
15782 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15783
15784 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015785 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015786 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015787 $TestResults .= " <headers>\n";
15788 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15789 {
15790 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15791 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15792 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15793 }
15794 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015795 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015796
15797 if(my @Sources = keys(%{$Registered_Sources{1}}))
15798 {
15799 $TestResults .= " <sources>\n";
15800 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15801 {
15802 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15803 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15804 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15805 }
15806 $TestResults .= " </sources>\n";
15807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808
15809 $TestResults .= " <libs>\n";
15810 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15811 {
15812 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15813 $TestResults .= " <name>$Library</name>\n";
15814 }
15815 $TestResults .= " </libs>\n";
15816
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015817 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015818 $TestResults .= " <types>".$TotalTypes."</types>\n";
15819
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015820 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15821 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015822 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15823
15824 # problem summary
15825 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15826 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15827
15828 $Problem_Summary .= " <problems_with_types>\n";
15829 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15830 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15831 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15832 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15833 $Problem_Summary .= " </problems_with_types>\n";
15834
15835 $Problem_Summary .= " <problems_with_symbols>\n";
15836 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15837 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15838 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015839 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015840 $Problem_Summary .= " </problems_with_symbols>\n";
15841
15842 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015843 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015844 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015845
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015846 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15847
15848 return ($TestInfo.$TestResults.$Problem_Summary, "");
15849 }
15850 else
15851 { # HTML
15852 # test info
15853 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015854 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015855 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetTitle</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015856
15857 my (@VInf1, @VInf2, $AddTestInfo) = ();
15858 if($Arch1 ne "unknown"
15859 and $Arch2 ne "unknown")
15860 { # CPU arch
15861 if($Arch1 eq $Arch2)
15862 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015863 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015864 }
15865 else
15866 { # go to the version number
15867 push(@VInf1, showArch($Arch1));
15868 push(@VInf2, showArch($Arch2));
15869 }
15870 }
15871 if($GccV1 ne "unknown"
15872 and $GccV2 ne "unknown"
15873 and $OStarget ne "windows")
15874 { # GCC version
15875 if($GccV1 eq $GccV2)
15876 { # go to the separate section
15877 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15878 }
15879 else
15880 { # go to the version number
15881 push(@VInf1, "gcc ".$GccV1);
15882 push(@VInf2, "gcc ".$GccV2);
15883 }
15884 }
15885 # show long version names with GCC version and CPU architecture name (if different)
15886 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15887 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15888 $TestInfo .= $AddTestInfo;
15889 #if($COMMON_LANGUAGE{1}) {
15890 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15891 #}
15892 if($ExtendedCheck) {
15893 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015895 if($JoinReport)
15896 {
15897 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015898 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015899 }
15900 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015901 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015902 }
15903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015904 $TestInfo .= "</table>\n";
15905
15906 # test results
15907 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015908 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015909
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015910 if(my @Headers = keys(%{$Registered_Headers{1}}))
15911 {
15912 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15913 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15914 }
15915 elsif($CheckObjectsOnly) {
15916 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15917 }
15918
15919 if(my @Sources = keys(%{$Registered_Sources{1}}))
15920 {
15921 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15922 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015924
15925 if(not $ExtendedCheck)
15926 {
15927 my $Libs_Link = "0";
15928 $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 +040015929 $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 +040015930 }
15931
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015932 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015934 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015935 if($JoinReport) {
15936 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15937 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015938 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015939 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015940 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15941 }
15942 else {
15943 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15944 }
15945 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015946 $TestResults .= "</table>\n";
15947
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015948 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015949 # problem summary
15950 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015951 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15953
15954 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015955 if($Added>0)
15956 {
15957 if($JoinReport) {
15958 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15959 }
15960 else {
15961 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15962 }
15963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015964 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015965 $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 +040015966
15967 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015968 if($Removed>0)
15969 {
15970 if($JoinReport) {
15971 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15972 }
15973 else {
15974 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15975 }
15976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015977 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015978 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15979 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015980
15981 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015982 $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 +040015983 $TH_Link = "n/a" if($CheckObjectsOnly);
15984 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015985 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15986 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015987
15988 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015989 $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 +040015990 $TM_Link = "n/a" if($CheckObjectsOnly);
15991 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015992 $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 +040015993
15994 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 $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 +040015996 $TL_Link = "n/a" if($CheckObjectsOnly);
15997 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015998 $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 +040015999
16000 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016001 $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 +040016002 $IH_Link = "n/a" if($CheckObjectsOnly);
16003 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016004 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16005 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016006
16007 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016008 $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 +040016009 $IM_Link = "n/a" if($CheckObjectsOnly);
16010 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016011 $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 +040016012
16013 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 $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 +040016015 $IL_Link = "n/a" if($CheckObjectsOnly);
16016 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016017 $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 +040016018
16019 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016020 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16021 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016022 }
16023 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016024 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016025 $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 +040016026
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016027 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016028 if($T_Other and not $CheckObjectsOnly)
16029 {
16030 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016031 $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 Ponomarenkoab282102012-03-11 11:57:02 +040016032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016033
16034 if($I_Other and not $CheckObjectsOnly)
16035 {
16036 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016037 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "S", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016039
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016040 if($C_Other and not $CheckObjectsOnly)
16041 {
16042 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16043 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16044 }
16045
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016046 $META_DATA .= "tool_version:$TOOL_VERSION";
16047 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016048 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16050 }
16051}
16052
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016053sub getStyle($$$)
16054{
16055 my ($Subj, $Act, $Num) = @_;
16056 my %Style = (
16057 "A"=>"new",
16058 "R"=>"failed",
16059 "S"=>"passed",
16060 "L"=>"warning",
16061 "M"=>"failed",
16062 "H"=>"failed"
16063 );
16064 if($Num>0) {
16065 return " class='".$Style{$Act}."'";
16066 }
16067 return "";
16068}
16069
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016070sub show_number($)
16071{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016072 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016073 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016074 my $Num = cut_off_number($_[0], 2, 0);
16075 if($Num eq "0")
16076 {
16077 foreach my $P (3 .. 7)
16078 {
16079 $Num = cut_off_number($_[0], $P, 1);
16080 if($Num ne "0") {
16081 last;
16082 }
16083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016084 }
16085 if($Num eq "0") {
16086 $Num = $_[0];
16087 }
16088 return $Num;
16089 }
16090 return $_[0];
16091}
16092
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016093sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016094{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016095 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016096 if($num!~/\./)
16097 {
16098 $num .= ".";
16099 foreach (1 .. $digs_to_cut-1) {
16100 $num .= "0";
16101 }
16102 }
16103 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16104 {
16105 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16106 $num .= "0";
16107 }
16108 }
16109 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16110 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16111 }
16112 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016113 if($z) {
16114 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016116 return $num;
16117}
16118
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016119sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016120{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016121 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016122 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016123
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016124 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016125 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16126 {
16127 my $Header = $Constants{1}{$Constant}{"Header"};
16128 if(not $Header)
16129 { # added
16130 $Header = $Constants{2}{$Constant}{"Header"}
16131 }
16132
16133 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16134 {
16135 if(not defined $CompatRules{$Level}{$Kind}) {
16136 next;
16137 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016138 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016139 next;
16140 }
16141 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016143 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016144
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016145 if($ReportFormat eq "xml")
16146 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016147 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016148 {
16149 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016150 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016151 {
16152 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016153 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16154 {
16155 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16156 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16157 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016158
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016159 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16160 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16161 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016162 if($Overcome) {
16163 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16164 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016165 $CHANGED_CONSTANTS .= " </problem>\n";
16166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016167 $CHANGED_CONSTANTS .= " </constant>\n";
16168 }
16169 $CHANGED_CONSTANTS .= " </header>\n";
16170 }
16171 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16172 }
16173 else
16174 { # HTML
16175 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016176 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016177 {
16178 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016179 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016180 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016181 my $Report = "";
16182
16183 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16184 {
16185 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16186 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16187 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16188 $Number += 1;
16189 }
16190 if($Report)
16191 {
16192 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16193 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16194 $Report = insertIDs($Report);
16195 }
16196 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016197 }
16198 $CHANGED_CONSTANTS .= "<br/>\n";
16199 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016200 if($CHANGED_CONSTANTS)
16201 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016202 my $Title = "Problems with Constants, $TargetSeverity Severity";
16203 if($TargetSeverity eq "Safe")
16204 { # Safe Changes
16205 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016206 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016207 $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 +040016208 }
16209 }
16210 return $CHANGED_CONSTANTS;
16211}
16212
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016213sub getTitle($$$)
16214{
16215 my ($Header, $Library, $NameSpace) = @_;
16216 my $Title = "";
16217 if($Library and $Library!~/\.\w+\Z/) {
16218 $Library .= " (.$LIB_EXT)";
16219 }
16220 if($Header and $Library)
16221 {
16222 $Title .= "<span class='h_name'>$Header</span>";
16223 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16224 }
16225 elsif($Library) {
16226 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16227 }
16228 elsif($Header) {
16229 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16230 }
16231 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016232 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016233 }
16234 return $Title;
16235}
16236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016237sub get_Report_Added($)
16238{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016239 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016240 my $ADDED_INTERFACES = "";
16241 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016242 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016243 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016244 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016245 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016246 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016247 {
16248 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16249 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016250 if($Level eq "Source" and $ReportFormat eq "html")
16251 { # do not show library name in HTML report
16252 $DyLib = "";
16253 }
16254 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255 }
16256 }
16257 }
16258 if($ReportFormat eq "xml")
16259 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016260 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016261 {
16262 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016263 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016264 {
16265 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016266 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016267 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16268 }
16269 $ADDED_INTERFACES .= " </library>\n";
16270 }
16271 $ADDED_INTERFACES .= " </header>\n";
16272 }
16273 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16274 }
16275 else
16276 { # HTML
16277 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016278 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016280 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016281 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016282 my %NameSpaceSymbols = ();
16283 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016284 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016286 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016287 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016288 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16289 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016290 foreach my $Interface (@SortedInterfaces)
16291 {
16292 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016293 my $Signature = get_Signature($Interface, 2);
16294 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016295 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016296 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016297 if($Interface=~/\A(_Z|\?)/)
16298 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 $ADDED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span><br/><br/>".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016301 }
16302 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016303 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016304 }
16305 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016306 else
16307 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016309 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016310 }
16311 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016312 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016313 }
16314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016315 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016316 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016318 }
16319 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016320 if($ADDED_INTERFACES)
16321 {
16322 my $Anchor = "<a name='Added'></a>";
16323 if($JoinReport) {
16324 $Anchor = "<a name='".$Level."_Added'></a>";
16325 }
16326 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016327 }
16328 }
16329 return $ADDED_INTERFACES;
16330}
16331
16332sub get_Report_Removed($)
16333{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016334 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016335 my $REMOVED_INTERFACES = "";
16336 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016337 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016338 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016339 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016340 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016341 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016343 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16344 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016345 if($Level eq "Source" and $ReportFormat eq "html")
16346 { # do not show library name in HTML report
16347 $DyLib = "";
16348 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016349 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016350 }
16351 }
16352 }
16353 if($ReportFormat eq "xml")
16354 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016355 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016356 {
16357 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016358 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016359 {
16360 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016361 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16362 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016363 }
16364 $REMOVED_INTERFACES .= " </library>\n";
16365 }
16366 $REMOVED_INTERFACES .= " </header>\n";
16367 }
16368 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16369 }
16370 else
16371 { # HTML
16372 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016373 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016375 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016376 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016377 my %NameSpaceSymbols = ();
16378 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016379 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016381 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016382 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016383 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16384 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016385 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016386 {
16387 $Removed_Number += 1;
16388 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016389 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016390 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016391 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016392 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016393 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016394 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016395 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016396 $REMOVED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span><br/><br/>".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 }
16398 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016399 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016400 }
16401 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016402 else
16403 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016404 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016405 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016406 }
16407 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016408 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016409 }
16410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016411 }
16412 }
16413 $REMOVED_INTERFACES .= "<br/>\n";
16414 }
16415 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016416 if($REMOVED_INTERFACES)
16417 {
16418 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16419 if($JoinReport) {
16420 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16421 }
16422 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016423 }
16424 }
16425 return $REMOVED_INTERFACES;
16426}
16427
16428sub getXmlParams($$)
16429{
16430 my ($Content, $Problem) = @_;
16431 return "" if(not $Content or not $Problem);
16432 my %XMLparams = ();
16433 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16434 {
16435 my $Macro = "\@".lc($Attr);
16436 if($Content=~/\Q$Macro\E/) {
16437 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16438 }
16439 }
16440 my @PString = ();
16441 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016442 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016443 }
16444 if(@PString) {
16445 return " ".join(" ", @PString);
16446 }
16447 else {
16448 return "";
16449 }
16450}
16451
16452sub addMarkup($)
16453{
16454 my $Content = $_[0];
16455 # auto-markup
16456 $Content=~s/\n[ ]*//; # spaces
16457 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16458 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016459 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016460 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16461 if($Content=~/\ANOTE:/)
16462 { # notes
16463 $Content=~s!(NOTE):!<b>$1</b>:!g;
16464 }
16465 else {
16466 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16467 }
16468 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16469 my @Keywords = (
16470 "void",
16471 "const",
16472 "static",
16473 "restrict",
16474 "volatile",
16475 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016476 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016477 );
16478 my $MKeys = join("|", @Keywords);
16479 foreach (@Keywords) {
16480 $MKeys .= "|non-".$_;
16481 }
16482 $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 +040016483
16484 # Markdown
16485 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16486 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 return $Content;
16488}
16489
16490sub applyMacroses($$$$)
16491{
16492 my ($Level, $Kind, $Content, $Problem) = @_;
16493 return "" if(not $Content or not $Problem);
16494 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16495 $Content = addMarkup($Content);
16496 # macros
16497 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16498 {
16499 my $Macro = "\@".lc($Attr);
16500 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016501 if(not defined $Value
16502 or $Value eq "") {
16503 next;
16504 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016505 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16508 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016509 $Value = black_name($Value);
16510 }
16511 elsif($Value=~/\s/) {
16512 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16513 }
16514 elsif($Value=~/\A\d+\Z/
16515 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16516 { # bits to bytes
16517 if($Value % $BYTE_SIZE)
16518 { # bits
16519 if($Value==1) {
16520 $Value = "<b>".$Value."</b> bit";
16521 }
16522 else {
16523 $Value = "<b>".$Value."</b> bits";
16524 }
16525 }
16526 else
16527 { # bytes
16528 $Value /= $BYTE_SIZE;
16529 if($Value==1) {
16530 $Value = "<b>".$Value."</b> byte";
16531 }
16532 else {
16533 $Value = "<b>".$Value."</b> bytes";
16534 }
16535 }
16536 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016537 else
16538 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016539 $Value = "<b>".htmlSpecChars($Value)."</b>";
16540 }
16541 $Content=~s/\Q$Macro\E/$Value/g;
16542 }
16543
16544 if($Content=~/(\A|[^\@\w])\@\w/)
16545 {
16546 if(not $IncompleteRules{$Level}{$Kind})
16547 { # only one warning
16548 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16549 $IncompleteRules{$Level}{$Kind} = 1;
16550 }
16551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016552 return $Content;
16553}
16554
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016555sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016556{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016557 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016558 my $INTERFACE_PROBLEMS = "";
16559 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016560
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016563 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16564 if($SV and defined $CompatProblems{$Level}{$SN}) {
16565 next;
16566 }
16567 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568 {
16569 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016571 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016572 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16573 my $DyLib = $Symbol_Library{1}{$Symbol};
16574 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016575 { # Symbol with Version
16576 $DyLib = $Symbol_Library{1}{$VSym};
16577 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016578 if(not $DyLib)
16579 { # const global data
16580 $DyLib = "";
16581 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016582 if($Level eq "Source" and $ReportFormat eq "html")
16583 { # do not show library name in HTML report
16584 $DyLib = "";
16585 }
16586 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16587 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016588 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016589 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16590 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016591 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016592 }
16593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016594 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16595 {
16596 delete($SymbolChanges{$Symbol}{$Kind});
16597 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016599 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016600 }
16601 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016602 if(not keys(%{$SymbolChanges{$Symbol}})) {
16603 delete($SymbolChanges{$Symbol});
16604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016605 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016607 if($ReportFormat eq "xml")
16608 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016609 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 {
16611 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016612 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016613 {
16614 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016615 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16616 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 {
16618 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16619 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16620 {
16621 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16622 {
16623 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016624 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016626 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16627 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16628 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16629 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16630 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016631 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16632 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 $INTERFACE_PROBLEMS .= " </problem>\n";
16635 }
16636 }
16637 $INTERFACE_PROBLEMS .= " </symbol>\n";
16638 }
16639 $INTERFACE_PROBLEMS .= " </library>\n";
16640 }
16641 $INTERFACE_PROBLEMS .= " </header>\n";
16642 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 }
16645 else
16646 { # HTML
16647 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016648 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016649 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016652 my (%NameSpaceSymbols, %NewSignature) = ();
16653 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016654 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016655 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016656 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016658 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016659 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016660 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 my $Signature = get_Signature($Symbol, 1);
16663 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016665 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016666 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016667 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016668 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016669 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016670 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016671 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016672 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 }
16674 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16675 {
16676 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016677 $SYMBOL_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>".$Effect."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016678 $ProblemNum += 1;
16679 $ProblemsNum += 1;
16680 }
16681 }
16682 }
16683 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016684 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016686 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016687 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016688 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016689 }
16690 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016691 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016693 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16694 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16695 if($NewSignature{$Symbol})
16696 { # argument list changed to
16697 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span><br/><span class='new_sign'>".highLight_Signature_Italic_Color($NewSignature{$Symbol})."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016698 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016699 if($Symbol=~/\A(_Z|\?)/) {
16700 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16701 }
16702 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16703 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016704 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016705 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016706 }
16707 }
16708 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016709 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 }
16711 }
16712 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016713
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016714 if($INTERFACE_PROBLEMS)
16715 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016716 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16717 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16718 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016719 { # Safe Changes
16720 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016722 $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 +040016723 }
16724 }
16725 return $INTERFACE_PROBLEMS;
16726}
16727
16728sub get_Report_TypeProblems($$)
16729{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016730 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016731 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016732 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016733
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016734 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016735 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016736 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016737 {
16738 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16739 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016740 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016741 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016742 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016743 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016744 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016745
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016746 if($Severity eq "Safe"
16747 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 next;
16749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016750
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016751 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16752 {
16753 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16754 { # select a problem with the highest priority
16755 next;
16756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016757 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016758
16759 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016760 }
16761 }
16762 }
16763 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 my %Kinds_Locations = ();
16766 foreach my $TypeName (keys(%TypeChanges))
16767 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016768 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016769 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16770 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016771 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016772 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016773 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016774 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016775 { # other priority
16776 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16777 next;
16778 }
16779 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16780 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016781 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016782 { # duplicate target
16783 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16784 next;
16785 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016786 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016787 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016788 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016789 }
16790 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16791 delete($TypeChanges{$TypeName}{$Kind});
16792 }
16793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016794 if(not keys(%{$TypeChanges{$TypeName}})) {
16795 delete($TypeChanges{$TypeName});
16796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016797 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016798
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016799 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 +040016800 if($ReportFormat eq "xml")
16801 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016802 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016803 {
16804 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016805 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016806 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016807 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016808 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16809 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016810 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 {
16812 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16813 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16814 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16815 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16816 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16817 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016818 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16819 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 $TYPE_PROBLEMS .= " </problem>\n";
16822 }
16823 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016824 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016825 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016826 $TYPE_PROBLEMS .= showVTables($TypeName);
16827 }
16828 $TYPE_PROBLEMS .= " </type>\n";
16829 }
16830 $TYPE_PROBLEMS .= " </header>\n";
16831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016832 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016833 }
16834 else
16835 { # HTML
16836 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016837 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016838 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016839 my (%NameSpace_Type) = ();
16840 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016841 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016842 }
16843 foreach my $NameSpace (sort keys(%NameSpace_Type))
16844 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016845 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016846 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 +040016847 foreach my $TypeName (@SortedTypes)
16848 {
16849 my $ProblemNum = 1;
16850 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016851
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016852 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16853 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016854 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016855 {
16856 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16857 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16858 {
16859 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16860 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16861 $ProblemNum += 1;
16862 $ProblemsNum += 1;
16863 }
16864 }
16865 }
16866 $ProblemNum -= 1;
16867 if($TYPE_REPORT)
16868 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016869 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016871 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 $ShowVTables = showVTables($TypeName);
16873 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016874
16875 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016876 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16877 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16878 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16879 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016880 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016881 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 }
16883 }
16884 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016885 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016886 }
16887 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 if($TYPE_PROBLEMS)
16890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16892 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016893 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 { # Safe Changes
16895 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016897 $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 +040016898 }
16899 }
16900 return $TYPE_PROBLEMS;
16901}
16902
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016903sub show_Type($$$)
16904{
16905 my ($Name, $Html, $LibVersion) = @_;
16906 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16907 $TType = lc($TType);
16908 if($TType=~/struct|union|enum/) {
16909 $Name=~s/\A\Q$TType\E //g;
16910 }
16911 if($Html) {
16912 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16913 }
16914 else {
16915 $Name = $TType." ".$Name;
16916 }
16917 return $Name;
16918}
16919
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016920sub get_Anchor($$$)
16921{
16922 my ($Kind, $Level, $Severity) = @_;
16923 if($JoinReport)
16924 {
16925 if($Severity eq "Safe") {
16926 return "Other_".$Level."_Changes_In_".$Kind."s";
16927 }
16928 else {
16929 return $Kind."_".$Level."_Problems_".$Severity;
16930 }
16931 }
16932 else
16933 {
16934 if($Severity eq "Safe") {
16935 return "Other_Changes_In_".$Kind."s";
16936 }
16937 else {
16938 return $Kind."_Problems_".$Severity;
16939 }
16940 }
16941}
16942
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016943sub showVTables($)
16944{
16945 my $TypeName = $_[0];
16946 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016947 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016948 if(defined $Type1{"VTable"}
16949 and keys(%{$Type1{"VTable"}}))
16950 {
16951 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016952 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016953 if(defined $Type2{"VTable"}
16954 and keys(%{$Type2{"VTable"}}))
16955 {
16956 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16957 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016958 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016959 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016960 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16961 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016962 }
16963 my $VTABLES = "";
16964 if($ReportFormat eq "xml")
16965 { # XML
16966 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016967 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016968 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016970 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16971 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 $VTABLES .= " </entry>\n";
16973 }
16974 $VTABLES .= " </vtable>\n\n";
16975 }
16976 else
16977 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016978 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016979 $VTABLES .= "<tr><th>Offset</th>";
16980 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016983 {
16984 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016985 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016986 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016987 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016988 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016989 $Color1 = " class='failed'";
16990 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991 }
16992 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016993 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016994 }
16995 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016996 $VTABLES .= "<tr><th>".$Index."</th>\n";
16997 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16998 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016999 }
17000 $VTABLES .= "</table><br/>\n";
17001 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017002 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017003 }
17004 return $VTABLES;
17005 }
17006 }
17007 return "";
17008}
17009
17010sub simpleVEntry($)
17011{
17012 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017013 if(not defined $VEntry
17014 or $VEntry eq "") {
17015 return "";
17016 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017017
17018 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017019 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17020 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17021 if($VEntry=~/\A_ZThn.+\Z/) {
17022 $VEntry = "non-virtual thunk";
17023 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017024 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 # support for old GCC versions
17026 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17027 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17028 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017029 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17030 return $VEntry;
17031}
17032
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017033sub adjustParamPos($$$)
17034{
17035 my ($Pos, $Symbol, $LibVersion) = @_;
17036 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17037 {
17038 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17039 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17040 {
17041 return $Pos-1;
17042 }
17043
17044 return $Pos;
17045 }
17046
17047 return undef;
17048}
17049
17050sub getParamPos($$$)
17051{
17052 my ($Name, $Symbol, $LibVersion) = @_;
17053
17054 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17055 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17056 {
17057 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17058 foreach (keys(%{$Info->{"Param"}}))
17059 {
17060 if($Info->{"Param"}{$_}{"name"} eq $Name)
17061 {
17062 return $_;
17063 }
17064 }
17065 }
17066
17067 return undef;
17068}
17069
17070sub getParamName($)
17071{
17072 my $Loc = $_[0];
17073 $Loc=~s/\->.*//g;
17074 return $Loc;
17075}
17076
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017077sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017079 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017080 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017081
17082 if(defined $AffectLimit)
17083 {
17084 $LIMIT = $AffectLimit;
17085 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017086
17087 my %SymSel = ();
17088 my %SymLocKind = ();
17089
17090 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017092 if(index($Symbol, "_Z")==0
17093 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 { # duplicated problems for C2 constructors, D2 and D0 destructors
17095 next;
17096 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017097
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017098 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017099 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017100 if(not defined $CompatProblems{$Level}{$Symbol}
17101 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17102 next;
17103 }
17104
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017105 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017106 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017107 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108 next;
17109 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017110
17111 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17112 if($Level eq "Source")
17113 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017114 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017115 }
17116
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017117 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017118 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 { # duplicated problems for versioned symbols
17120 next;
17121 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017122
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017123 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017124 if($Type_Name ne $Target_TypeName) {
17125 next;
17126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017127
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017128 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129 }
17130 }
17131 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017132
17133 foreach my $Symbol (sort keys(%SymLocKind))
17134 {
17135 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17136 {
17137 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17138 {
17139 $SymSel{$Symbol}{"Loc"} = $Loc;
17140 $SymSel{$Symbol}{"Kind"} = $Kind;
17141
17142 last LOOP;
17143 }
17144 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017145 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017146
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017147 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017148 my $Num = 0;
17149
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017150 if($ReportFormat eq "xml")
17151 { # XML
17152 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017153
17154 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017156 my $PName = getParamName($Loc);
17157 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17158
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017159 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017160 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017161 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017162 $Target .= " param=\"$PName\"";
17163 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017164 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017165 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017166 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017167 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017168 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017169 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017170 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017171
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017172 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017173 $Target .= " field=\"$1\"";
17174 }
17175
17176 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017177 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017179
17180 if($Num>$LIMIT) {
17181 last LOOP;
17182 }
17183
17184 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017185 }
17186 $Affected .= " </affected>\n";
17187 }
17188 else
17189 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017190 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017191 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017192 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17193 my $S = get_Signature($Symbol, 1);
17194 my $PName = getParamName($SymSel{$Symbol}{"Loc"});print "$Symbol\n" if($Symbol eq "sftp_file_set_blocking");
17195 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17196
17197 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17198 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17199
17200 if($Num>$LIMIT) {
17201 last;
17202 }
17203
17204 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017205 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017206
17207 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017208 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017209 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017210
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017211 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017212 if($Affected)
17213 {
17214 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017215 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017216 }
17217 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017218
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017219 return $Affected;
17220}
17221
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017222sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017224 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017225 if($L2=~/\A(retval|this)\b/
17226 and $L1!~/\A(retval|this)\b/)
17227 {
17228 if($L1!~/\-\>/) {
17229 return 1;
17230 }
17231 elsif($L2=~/\-\>/) {
17232 return 1;
17233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017234 }
17235 return 0;
17236}
17237
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017238sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017239{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017240 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017241
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017242 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017243
17244 my $Location_I = $Location;
17245 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17246
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017247 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017248
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017249 if($Kind eq "Overridden_Virtual_Method"
17250 or $Kind eq "Overridden_Virtual_Method_B") {
17251 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17252 }
17253 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17254 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017255 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17258 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017259 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17260 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17261
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017262 if($ClassName eq $Problem{"Type_Name"}) {
17263 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17264 }
17265 else {
17266 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17267 }
17268 }
17269 else
17270 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017271 my $TypeID = undef;
17272
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017273 if($Location=~/retval/)
17274 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017275 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017276 push(@Sentence, "Field \'".$Location."\' in return value");
17277 }
17278 else {
17279 push(@Sentence, "Return value");
17280 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017281
17282 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017283 }
17284 elsif($Location=~/this/)
17285 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017286 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017287 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17288 }
17289 else {
17290 push(@Sentence, "\'this\' pointer");
17291 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017292
17293 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017294 }
17295 else
17296 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017297
17298 my $PName = getParamName($Location);
17299 my $PPos = getParamPos($PName, $Symbol, 1);
17300
17301 if(index($Location, "->")!=-1) {
17302 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017303 }
17304 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017305 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017306 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017307 if($PName) {
17308 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017309 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017310
17311 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17312 }
17313
17314 if($Location!~/this/)
17315 {
17316 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017317 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017318 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017319 push(@Sentence, "(pointer)");
17320 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017321 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017322 push(@Sentence, "(reference)");
17323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017324 }
17325 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017326
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017327 if($Location eq "this") {
17328 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17329 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017330 else
17331 {
17332 my $Location_T = $Location;
17333 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17334
17335 my $TypeID_Problem = $TypeID;
17336 if($Location_T) {
17337 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17338 }
17339
17340 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17341 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17342 }
17343 else {
17344 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017346 }
17347 }
17348 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017349 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017350 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 +040017351 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017352
17353 my $Sent = join(" ", @Sentence);
17354
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017355 $Sent=~s/->/./g;
17356
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017357 if($ReportFormat eq "xml")
17358 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017359 $Sent=~s/'//g;
17360 }
17361
17362 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017363}
17364
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017365sub getFieldType($$$)
17366{
17367 my ($Location, $TypeId, $LibVersion) = @_;
17368
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017369 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017370
17371 foreach my $Name (@Fields)
17372 {
17373 my %Info = get_BaseType($TypeId, $LibVersion);
17374
17375 foreach my $Pos (keys(%{$Info{"Memb"}}))
17376 {
17377 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17378 {
17379 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17380 last;
17381 }
17382 }
17383 }
17384
17385 return $TypeId;
17386}
17387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017388sub get_XmlSign($$)
17389{
17390 my ($Symbol, $LibVersion) = @_;
17391 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17392 my $Report = "";
17393 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17394 {
17395 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017396 my $Type = $Info->{"Param"}{$Pos}{"type"};
17397 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017398 foreach my $Typedef (keys(%ChangedTypedef))
17399 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017400 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17401 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17402 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017403 }
17404 $Report .= " <param pos=\"$Pos\">\n";
17405 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017406 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017407 $Report .= " </param>\n";
17408 }
17409 if(my $Return = $Info->{"Return"})
17410 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017411 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017413 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017414 $Report .= " </retval>\n";
17415 }
17416 return $Report;
17417}
17418
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017419sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017420{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017421 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017422 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017423 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017424 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017425 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17426 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017427 next;
17428 }
17429 $Report .= " <symbol name=\"$Symbol\">\n";
17430 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017431 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 {
17433 if(defined $CompleteSignature{1}{$Symbol}
17434 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17435 {
17436 $P1 = get_XmlSign($Symbol, 1);
17437 $S1 = get_Signature($Symbol, 1);
17438 }
17439 elsif($Symbol=~/\A(_Z|\?)/) {
17440 $S1 = $tr_name{$Symbol};
17441 }
17442 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017443 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017444 {
17445 if(defined $CompleteSignature{2}{$Symbol}
17446 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17447 {
17448 $P2 = get_XmlSign($Symbol, 2);
17449 $S2 = get_Signature($Symbol, 2);
17450 }
17451 elsif($Symbol=~/\A(_Z|\?)/) {
17452 $S2 = $tr_name{$Symbol};
17453 }
17454 }
17455 if($S1)
17456 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017457 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017458 $Report .= $P1;
17459 $Report .= " </old>\n";
17460 }
17461 if($S2 and $S2 ne $S1)
17462 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017463 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017464 $Report .= $P2;
17465 $Report .= " </new>\n";
17466 }
17467 $Report .= " </symbol>\n";
17468 }
17469 $Report .= "</symbols_info>\n";
17470 return $Report;
17471}
17472
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017473sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017475 my ($Level, $Report) = @_;
17476 if($ReportFormat eq "xml") {
17477 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017478 }
17479 if($StdOut)
17480 { # --stdout option
17481 print STDOUT $Report;
17482 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017483 else
17484 {
17485 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017486 mkpath(get_dirname($RPath));
17487
17488 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17489 print REPORT $Report;
17490 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017491 }
17492}
17493
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017494sub getReport($)
17495{
17496 my $Level = $_[0];
17497 if($ReportFormat eq "xml")
17498 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017499 if($Level eq "Join")
17500 {
17501 my $Report = "<reports>\n";
17502 $Report .= getReport("Binary");
17503 $Report .= getReport("Source");
17504 $Report .= "</reports>\n";
17505 return $Report;
17506 }
17507 else
17508 {
17509 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17510 my ($Summary, $MetaData) = get_Summary($Level);
17511 $Report .= $Summary."\n";
17512 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17513 $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 +040017514
17515 # additional symbols info (if needed)
17516 # $Report .= get_Report_SymbolsInfo($Level);
17517
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017518 $Report .= "</report>\n";
17519 return $Report;
17520 }
17521 }
17522 else
17523 { # HTML
17524 my $CssStyles = readModule("Styles", "Report.css");
17525 my $JScripts = readModule("Scripts", "Sections.js");
17526 if($Level eq "Join")
17527 {
17528 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17529 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017530 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17531 my $Keywords = $TargetTitle.", compatibility, API, report";
17532 my $Description = "Compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017533 my ($BSummary, $BMetaData) = get_Summary("Binary");
17534 my ($SSummary, $SMetaData) = get_Summary("Source");
17535 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 +030017536 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017537 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017538 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17539 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017540 </div>";
17541 $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>";
17542 $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 Ponomarenko14b8f022015-08-13 20:19:32 +030017543 $Report .= getReportFooter($TargetTitle, not $JoinReport);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017544 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017545 return $Report;
17546 }
17547 else
17548 {
17549 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017550 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17551 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17552 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 +040017553 if($Level eq "Binary")
17554 {
17555 if(getArch(1) eq getArch(2)
17556 and getArch(1) ne "unknown") {
17557 $Description .= " on ".showArch(getArch(1));
17558 }
17559 }
17560 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 +030017561 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017562 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17563 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17564 $Report .= get_SourceInfo();
17565 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017566 $Report .= getReportFooter($TargetTitle, not $JoinReport);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017567 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017568 return $Report;
17569 }
17570 }
17571}
17572
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017573sub getLegend()
17574{
17575 return "<br/>
17576<table class='summary'>
17577<tr>
17578 <td class='new'>added</td>
17579 <td class='passed'>compatible</td>
17580</tr>
17581<tr>
17582 <td class='warning'>warning</td>
17583 <td class='failed'>incompatible</td>
17584</tr></table>\n";
17585}
17586
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017587sub createReport()
17588{
17589 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017590 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017591 writeReport("Join", getReport("Join"));
17592 }
17593 elsif($DoubleReport)
17594 { # default
17595 writeReport("Binary", getReport("Binary"));
17596 writeReport("Source", getReport("Source"));
17597 }
17598 elsif($BinaryOnly)
17599 { # --binary
17600 writeReport("Binary", getReport("Binary"));
17601 }
17602 elsif($SourceOnly)
17603 { # --source
17604 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017605 }
17606}
17607
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017608sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017609{
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017610 my ($LibName, $Single) = @_;
17611 my $Class = "footer";
17612 if(not $Single) {
17613 $Class .= " double_report";
17614 }
17615 my $Footer = "<div class=\'$Class\' align='right'><i>Generated on ".(localtime time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017616 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017617 $Footer .= "</i></div>";
17618 $Footer .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017619 return $Footer;
17620}
17621
17622sub get_Report_Problems($$)
17623{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017624 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017625
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017626 my $Report = get_Report_TypeProblems($Severity, $Level);
17627 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017628 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017629 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017630
17631 if($Severity eq "Low" or $Severity eq "Safe") {
17632 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017633 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017634
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017635 if($ReportFormat eq "html")
17636 {
17637 if($Report)
17638 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017639 if($JoinReport)
17640 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017641 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017642 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17643 }
17644 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017645 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017648 else
17649 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017650 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017651 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17652 }
17653 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017654 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017655 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 }
17657 }
17658 }
17659 return $Report;
17660}
17661
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017662sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017663{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017664 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17665 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17666 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17667 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017668 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17669 <meta name=\"keywords\" content=\"$Keywords\" />
17670 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017671 <title>
17672 $Title
17673 </title>
17674 <style type=\"text/css\">
17675 $Styles
17676 </style>
17677 <script type=\"text/javascript\" language=\"JavaScript\">
17678 <!--
17679 $Scripts
17680 -->
17681 </script>
17682 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017683}
17684
17685sub insertIDs($)
17686{
17687 my $Text = $_[0];
17688 while($Text=~/CONTENT_ID/)
17689 {
17690 if(int($Content_Counter)%2) {
17691 $ContentID -= 1;
17692 }
17693 $Text=~s/CONTENT_ID/c_$ContentID/;
17694 $ContentID += 1;
17695 $Content_Counter += 1;
17696 }
17697 return $Text;
17698}
17699
17700sub checkPreprocessedUnit($)
17701{
17702 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017703 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017704 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017705 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017706
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017707 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017708 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017709 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017710 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017711 chomp($Line);
17712 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017713 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017714 $CurHeader = path_format($1, $OSgroup);
17715 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017716 $CurClass = "";
17717
17718 if(index($CurHeader, $TMP_DIR)==0) {
17719 next;
17720 }
17721
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017722 if(substr($CurHeaderName, 0, 1) eq "<")
17723 { # <built-in>, <command-line>, etc.
17724 $CurHeaderName = "";
17725 $CurHeader = "";
17726 }
17727
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017728 if($ExtraInfo)
17729 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017730 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017731 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17732 }
17733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017734 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017735 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017736 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017737 if($CurHeaderName)
17738 {
17739 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17740 and not $Registered_Headers{$Version}{$CurHeader})
17741 { # not a target
17742 next;
17743 }
17744 if(not is_target_header($CurHeaderName, 1)
17745 and not is_target_header($CurHeaderName, 2))
17746 { # user-defined header
17747 next;
17748 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017749 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017750 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017751
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017752 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017753 {
17754 my ($Name, $Value) = ($1, $2);
17755 if(not $Constants{$Version}{$Name}{"Access"})
17756 {
17757 $Constants{$Version}{$Name}{"Access"} = "public";
17758 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017759 if($CurHeaderName) {
17760 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17761 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017762 }
17763 }
17764 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17765 $Constants{$Version}{$1}{"Access"} = "private";
17766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017767 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017768 else
17769 {
17770 if(defined $ExtraDump)
17771 {
17772 if($Line=~/(\w+)\s*\(/)
17773 { # functions
17774 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17775 }
17776 #elsif($Line=~/(\w+)\s*;/)
17777 #{ # data
17778 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17779 #}
17780 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17781 $CurClass = $2;
17782 }
17783 }
17784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017785 }
17786 close(PREPROC);
17787 foreach my $Constant (keys(%{$Constants{$Version}}))
17788 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017789 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17790 {
17791 delete($Constants{$Version}{$Constant});
17792 next;
17793 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017794 if(not $ExtraDump and ($Constant=~/_h\Z/i
17795 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017796 { # skip
17797 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017798 }
17799 else {
17800 delete($Constants{$Version}{$Constant}{"Access"});
17801 }
17802 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017803 if($Debug)
17804 {
17805 mkpath($DEBUG_PATH{$Version});
17806 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017808}
17809
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017810sub uncoverConstant($$)
17811{
17812 my ($LibVersion, $Constant) = @_;
17813 return "" if(not $LibVersion or not $Constant);
17814 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17815 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17816 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17817 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017818
17819 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017820 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017821 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17822 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017823 {
17824 push(@RecurConstant, $Constant);
17825 my $Uncovered = uncoverConstant($LibVersion, $Value);
17826 if($Uncovered ne "") {
17827 $Value = $Uncovered;
17828 }
17829 pop(@RecurConstant);
17830 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017831
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017832 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017833 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017834 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17835 }
17836 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17837}
17838
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017839sub simpleConstant($$)
17840{
17841 my ($LibVersion, $Value) = @_;
17842 if($Value=~/\W/)
17843 {
17844 my $Value_Copy = $Value;
17845 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17846 {
17847 my $Word = $1;
17848 if($Value!~/$Word\s*\(/)
17849 {
17850 my $Val = uncoverConstant($LibVersion, $Word);
17851 if($Val ne "")
17852 {
17853 $Value=~s/\b$Word\b/$Val/g;
17854 }
17855 }
17856 }
17857 }
17858 return $Value;
17859}
17860
17861sub computeValue($)
17862{
17863 my $Value = $_[0];
17864
17865 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17866 return $1;
17867 }
17868
17869 if($Value=~/\A[\d\-\+()]+\Z/) {
17870 return eval($Value);
17871 }
17872
17873 return $Value;
17874}
17875
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017876my %IgnoreConstant = map {$_=>1} (
17877 "VERSION",
17878 "VERSIONCODE",
17879 "VERNUM",
17880 "VERS_INFO",
17881 "PATCHLEVEL",
17882 "INSTALLPREFIX",
17883 "VBUILD",
17884 "VPATCH",
17885 "VMINOR",
17886 "BUILD_STRING",
17887 "BUILD_TIME",
17888 "PACKAGE_STRING",
17889 "PRODUCTION",
17890 "CONFIGURE_COMMAND",
17891 "INSTALLDIR",
17892 "BINDIR",
17893 "CONFIG_FILE_PATH",
17894 "DATADIR",
17895 "EXTENSION_DIR",
17896 "INCLUDE_PATH",
17897 "LIBDIR",
17898 "LOCALSTATEDIR",
17899 "SBINDIR",
17900 "SYSCONFDIR",
17901 "RELEASE",
17902 "SOURCE_ID",
17903 "SUBMINOR",
17904 "MINOR",
17905 "MINNOR",
17906 "MINORVERSION",
17907 "MAJOR",
17908 "MAJORVERSION",
17909 "MICRO",
17910 "MICROVERSION",
17911 "BINARY_AGE",
17912 "INTERFACE_AGE",
17913 "CORE_ABI",
17914 "PATCH",
17915 "COPYRIGHT",
17916 "TIMESTAMP",
17917 "REVISION",
17918 "PACKAGE_TAG",
17919 "PACKAGEDATE",
17920 "NUMVERSION",
17921 "Release",
17922 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017923);
17924
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017925sub constantFilter($$$)
17926{
17927 my ($Name, $Value, $Level) = @_;
17928
17929 if($Level eq "Binary")
17930 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017931 if($Name=~/_t\Z/)
17932 { # __malloc_ptr_t
17933 return 1;
17934 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017935 foreach (keys(%IgnoreConstant))
17936 {
17937 if($Name=~/(\A|_)$_(_|\Z)/)
17938 { # version
17939 return 1;
17940 }
17941 if(/\A[A-Z].*[a-z]\Z/)
17942 {
17943 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17944 { # version
17945 return 1;
17946 }
17947 }
17948 }
17949 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17950 { # version
17951 return 1;
17952 }
17953 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17954 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17955 return 1;
17956 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017957
17958 if($Value=~/\A["'].*['"]/i)
17959 { # string
17960 return 0;
17961 }
17962
17963 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17964 { # static int gcry_pth_init
17965 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017966 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017967 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017968 return 1;
17969 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017970 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017971 { # foo(p)
17972 return 1;
17973 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017974 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017975 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017976 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017977 return 1;
17978 }
17979 }
17980
17981 return 0;
17982}
17983
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017984sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017985{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017986 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017987 foreach my $Constant (keys(%{$Constants{1}}))
17988 {
17989 if($SkipConstants{1}{$Constant})
17990 { # skipped by the user
17991 next;
17992 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017993
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017994 if(my $Header = $Constants{1}{$Constant}{"Header"})
17995 {
17996 if(not is_target_header($Header, 1)
17997 and not is_target_header($Header, 2))
17998 { # user-defined header
17999 next;
18000 }
18001 }
18002 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018003 next;
18004 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018005
18006 my $Old_Value = uncoverConstant(1, $Constant);
18007
18008 if(constantFilter($Constant, $Old_Value, $Level))
18009 { # separate binary and source problems
18010 next;
18011 }
18012
18013 if(not defined $Constants{2}{$Constant}{"Value"})
18014 { # removed
18015 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18016 "Target"=>$Constant,
18017 "Old_Value"=>$Old_Value );
18018 next;
18019 }
18020
18021 if($Constants{2}{$Constant}{"Value"} eq "")
18022 { # empty value
18023 # TODO: implement a rule
18024 next;
18025 }
18026
18027 my $New_Value = uncoverConstant(2, $Constant);
18028
18029 my $Old_Value_Pure = $Old_Value;
18030 my $New_Value_Pure = $New_Value;
18031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018032 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18033 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18034 $New_Value_Pure=~s/(\W)\s+/$1/g;
18035 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018037 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018039 if($New_Value_Pure ne $Old_Value_Pure)
18040 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018041 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18042 { # complex values
18043 next;
18044 }
18045 if(computeValue($Old_Value) eq computeValue($New_Value))
18046 { # expressions
18047 next;
18048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018049 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18050 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18051 next;
18052 }
18053 if($Old_Value eq "0" and $New_Value eq "NULL")
18054 { # 0 => NULL
18055 next;
18056 }
18057 if($Old_Value eq "NULL" and $New_Value eq "0")
18058 { # NULL => 0
18059 next;
18060 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018061 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018062 "Target"=>$Constant,
18063 "Old_Value"=>$Old_Value,
18064 "New_Value"=>$New_Value );
18065 }
18066 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018067
18068 foreach my $Constant (keys(%{$Constants{2}}))
18069 {
18070 if(not defined $Constants{1}{$Constant}{"Value"})
18071 {
18072 if($SkipConstants{2}{$Constant})
18073 { # skipped by the user
18074 next;
18075 }
18076
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018077 if(my $Header = $Constants{2}{$Constant}{"Header"})
18078 {
18079 if(not is_target_header($Header, 1)
18080 and not is_target_header($Header, 2))
18081 { # user-defined header
18082 next;
18083 }
18084 }
18085 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018086 next;
18087 }
18088
18089 my $New_Value = uncoverConstant(2, $Constant);
18090 if(not defined $New_Value or $New_Value eq "") {
18091 next;
18092 }
18093
18094 if(constantFilter($Constant, $New_Value, $Level))
18095 { # separate binary and source problems
18096 next;
18097 }
18098
18099 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18100 "Target"=>$Constant,
18101 "New_Value"=>$New_Value );
18102 }
18103 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018104}
18105
18106sub convert_integer($)
18107{
18108 my $Value = $_[0];
18109 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018110 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018111 return hex($Value);
18112 }
18113 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018114 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018115 return oct($Value);
18116 }
18117 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018118 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018119 return oct($Value);
18120 }
18121 else {
18122 return $Value;
18123 }
18124}
18125
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018126sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018127{
18128 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018129 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018130 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018131 {
18132 if($LibVersion==1)
18133 {
18134 printMsg("WARNING", "checking headers only");
18135 $CheckHeadersOnly = 1;
18136 }
18137 else {
18138 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18139 }
18140 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018141
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018142 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018143 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018144 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018145
18146 if($CheckUndefined)
18147 {
18148 my %UndefinedLibs = ();
18149
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018150 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18151
18152 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018153 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018154 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018155 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018156 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018157 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018158 if($Symbol_Library{$LibVersion}{$Symbol}
18159 or $DepSymbol_Library{$LibVersion}{$Symbol})
18160 { # exported by target library
18161 next;
18162 }
18163 if(index($Symbol, '@')!=-1)
18164 { # exported default symbol version (@@)
18165 $Symbol=~s/\@/\@\@/;
18166 if($Symbol_Library{$LibVersion}{$Symbol}
18167 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18168 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018169 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018170 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018171 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18172 $UndefinedLibs{$Path} = 1;
18173 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018174 }
18175 }
18176 }
18177 if($ExtraInfo)
18178 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018179 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018180 {
18181 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018182 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018183 foreach (@Paths)
18184 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018185 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018186 my ($Dir, $Name) = separate_path($_);
18187
18188 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018189 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018190 }
18191
18192 $Name = parse_libname($Name, "name", $OStarget);
18193 $Name=~s/\Alib//;
18194
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018195 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018196 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018197
18198 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18199 {
18200 $LibString = " -L".esc($Dir).$LibString;
18201 }
18202
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018203 writeFile($ExtraInfo."/libs-string", $LibString);
18204 }
18205 }
18206 }
18207
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018208 if($ExtraInfo) {
18209 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18210 }
18211
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018212 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018213 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018214 if($#LibPaths!=-1)
18215 {
18216 if(not keys(%{$Symbol_Library{$LibVersion}}))
18217 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018218 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018219 printMsg("WARNING", "checking headers only");
18220 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018221 }
18222 }
18223 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018224
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018225 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018226 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018227}
18228
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018229my %Prefix_Lib_Map=(
18230 # symbols for autodetecting library dependencies (by prefix)
18231 "pthread_" => ["libpthread"],
18232 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18233 "cairo_" => ["libcairo"],
18234 "gtk_" => ["libgtk-x11-2.0"],
18235 "atk_" => ["libatk-1.0"],
18236 "gdk_" => ["libgdk-x11-2.0"],
18237 "gl" => ["libGL"],
18238 "glu" => ["libGLU"],
18239 "popt" => ["libpopt"],
18240 "Py" => ["libpython"],
18241 "jpeg_" => ["libjpeg"],
18242 "BZ2_" => ["libbz2"],
18243 "Fc" => ["libfontconfig"],
18244 "Xft" => ["libXft"],
18245 "SSL_" => ["libssl"],
18246 "sem_" => ["libpthread"],
18247 "snd_" => ["libasound"],
18248 "art_" => ["libart_lgpl_2"],
18249 "dbus_g" => ["libdbus-glib-1"],
18250 "GOMP_" => ["libgomp"],
18251 "omp_" => ["libgomp"],
18252 "cms" => ["liblcms"]
18253);
18254
18255my %Pattern_Lib_Map=(
18256 "SL[a-z]" => ["libslang"]
18257);
18258
18259my %Symbol_Lib_Map=(
18260 # symbols for autodetecting library dependencies (by name)
18261 "pow" => "libm",
18262 "fmod" => "libm",
18263 "sin" => "libm",
18264 "floor" => "libm",
18265 "cos" => "libm",
18266 "dlopen" => "libdl",
18267 "deflate" => "libz",
18268 "inflate" => "libz",
18269 "move_panel" => "libpanel",
18270 "XOpenDisplay" => "libX11",
18271 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018272 "clock_gettime" => "librt",
18273 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018274);
18275
18276sub find_SymbolLibs($$)
18277{
18278 my ($LibVersion, $Symbol) = @_;
18279
18280 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18281 { # debug symbols
18282 return ();
18283 }
18284
18285 my %Paths = ();
18286
18287 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18288 {
18289 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18290 $Paths{$Path} = 1;
18291 }
18292 }
18293
18294 if(my $SymbolPrefix = getPrefix($Symbol))
18295 {
18296 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18297 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18298 }
18299
18300 if(not keys(%Paths))
18301 {
18302 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18303 {
18304 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18305 {
18306 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18307 $Paths{$Path} = 1;
18308 }
18309 }
18310 }
18311 }
18312
18313 if(not keys(%Paths))
18314 {
18315 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18316 {
18317 if($Symbol=~/\A$Prefix/)
18318 {
18319 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18320 {
18321 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18322 $Paths{$Path} = 1;
18323 }
18324 }
18325 }
18326 }
18327 }
18328
18329 if(not keys(%Paths))
18330 {
18331 if($SymbolPrefix)
18332 { # try to find a library by symbol prefix
18333 if($SymbolPrefix eq "inotify" and
18334 index($Symbol, "\@GLIBC")!=-1)
18335 {
18336 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18337 $Paths{$Path} = 1;
18338 }
18339 }
18340 else
18341 {
18342 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18343 $Paths{$Path} = 1;
18344 }
18345 }
18346 }
18347 }
18348
18349 if(my @Paths = keys(%Paths)) {
18350 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18351 }
18352 }
18353 return keys(%Paths);
18354}
18355
18356sub get_LibPath_Prefix($$)
18357{
18358 my ($LibVersion, $Prefix) = @_;
18359
18360 $Prefix = lc($Prefix);
18361 $Prefix=~s/[_]+\Z//g;
18362
18363 foreach ("-2", "2", "-1", "1", "")
18364 { # libgnome-2.so
18365 # libxml2.so
18366 # libdbus-1.so
18367 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18368 return $Path;
18369 }
18370 }
18371 return "";
18372}
18373
18374sub getPrefix($)
18375{
18376 my $Str = $_[0];
18377 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18378 { # XmuValidArea: Xmu
18379 return $1;
18380 }
18381 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18382 { # snfReadFont: snf
18383 return $1;
18384 }
18385 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18386 { # XRRTimes: XRR
18387 return $1;
18388 }
18389 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18390 { # H5HF_delete: H5
18391 return $1;
18392 }
18393 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18394 { # alarm_event_add: alarm_
18395 return $1;
18396 }
18397 elsif($Str=~/\A(([a-z])\2{1,})/i)
18398 { # ffopen
18399 return $1;
18400 }
18401 return "";
18402}
18403
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018404sub getSymbolSize($$)
18405{ # size from the shared library
18406 my ($Symbol, $LibVersion) = @_;
18407 return 0 if(not $Symbol);
18408 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18409 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18410 {
18411 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18412 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18413 {
18414 if($Size<0) {
18415 return -$Size;
18416 }
18417 }
18418 }
18419 return 0;
18420}
18421
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018422sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018423{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18424 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018425 my ($Name, $Type) = @_;
18426
18427 # single
18428 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018429 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018430 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018431 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018432 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018433
18434 # double
18435 if($Name=~/$DEFAULT_STD_PARMS/)
18436 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018437 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018438 {
18439 my ($ShortName, $FuncParams) = split_Signature($Name);
18440
18441 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18442 {
18443 if(index($FParam, "<")!=-1)
18444 {
18445 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18446 my $FParam_N = canonifyName($FParam, "T");
18447 if($FParam_N ne $FParam) {
18448 $Name=~s/\Q$FParam\E/$FParam_N/g;
18449 }
18450 }
18451 }
18452 }
18453 elsif($Type eq "T")
18454 {
18455 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18456
18457 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018458 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018459 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018460 my $FParam = $TParams[0];
18461 foreach my $Pos (1 .. $#TParams)
18462 {
18463 my $TParam = $TParams[$Pos];
18464 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18465 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18466 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018467 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018468 }
18469 }
18470 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018471 if($Type eq "S") {
18472 return formatName($Name, "S");
18473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018474 return $Name;
18475}
18476
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018477sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018478{
18479 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018480 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018481 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018482 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018483 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018484 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018485 next if($tr_name{$Symbol});
18486 $Symbol=~s/[\@\$]+(.*)\Z//;
18487 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018488 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018489 elsif(index($Symbol, "?")==0)
18490 {
18491 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018492 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018493 }
18494 else
18495 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018496 $tr_name{$Symbol} = $Symbol;
18497 $mangled_name_gcc{$Symbol} = $Symbol;
18498 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499 }
18500 }
18501 if($#MnglNames1 > -1)
18502 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018503 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018504 foreach my $MnglName (@MnglNames1)
18505 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018506 if(my $Unmangled = pop(@UnmangledNames))
18507 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018508 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018509 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18510 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18511 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018512 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018513 and $tr_name{$MnglName}=~/vtable for (.+)/)
18514 { # bind class name and v-table symbol
18515 my $ClassName = $1;
18516 $ClassVTable{$ClassName} = $MnglName;
18517 $VTableClass{$MnglName} = $ClassName;
18518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018519 }
18520 }
18521 }
18522 if($#MnglNames2 > -1)
18523 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018524 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018525 foreach my $MnglName (@MnglNames2)
18526 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018527 if(my $Unmangled = pop(@UnmangledNames))
18528 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018529 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018530 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018532 }
18533 }
18534 return \%tr_name;
18535}
18536
18537sub link_symbol($$$)
18538{
18539 my ($Symbol, $RunWith, $Deps) = @_;
18540 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18541 return 1;
18542 }
18543 if($Deps eq "+Deps")
18544 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018545 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018546 return 1;
18547 }
18548 }
18549 return 0;
18550}
18551
18552sub link_symbol_internal($$$)
18553{
18554 my ($Symbol, $RunWith, $Where) = @_;
18555 return 0 if(not $Where or not $Symbol);
18556 if($Where->{$RunWith}{$Symbol})
18557 { # the exact match by symbol name
18558 return 1;
18559 }
18560 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18561 { # indirect symbol version, i.e.
18562 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018563 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018564 if($Where->{$RunWith}{$VSym}) {
18565 return 1;
18566 }
18567 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018568 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018569 if($Sym and $Ver)
18570 { # search for the symbol with the same version
18571 # or without version
18572 if($Where->{$RunWith}{$Sym})
18573 { # old: foo@v|foo@@v
18574 # new: foo
18575 return 1;
18576 }
18577 if($Where->{$RunWith}{$Sym."\@".$Ver})
18578 { # old: foo|foo@@v
18579 # new: foo@v
18580 return 1;
18581 }
18582 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18583 { # old: foo|foo@v
18584 # new: foo@@v
18585 return 1;
18586 }
18587 }
18588 return 0;
18589}
18590
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018591sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018592{
18593 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018594 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018595 my @Imported = ();
18596 if($OSgroup eq "macos")
18597 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018598 my $NM = get_CmdPath("nm");
18599 if(not $NM) {
18600 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018601 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018602 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018603 while(<APP>)
18604 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018605 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018606 push(@Imported, $1);
18607 }
18608 }
18609 close(APP);
18610 }
18611 elsif($OSgroup eq "windows")
18612 {
18613 my $DumpBinCmd = get_CmdPath("dumpbin");
18614 if(not $DumpBinCmd) {
18615 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18616 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018617 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018618 while(<APP>)
18619 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018620 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18621 push(@Imported, $1);
18622 }
18623 }
18624 close(APP);
18625 }
18626 else
18627 {
18628 my $ReadelfCmd = get_CmdPath("readelf");
18629 if(not $ReadelfCmd) {
18630 exitStatus("Not_Found", "can't find \"readelf\"");
18631 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018632 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018633 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018634 while(<APP>)
18635 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018636 if(defined $symtab)
18637 { # do nothing with symtab
18638 if(index($_, "'.dynsym'")!=-1)
18639 { # dynamic table
18640 $symtab = undef;
18641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018642 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018643 elsif(index($_, "'.symtab'")!=-1)
18644 { # symbol table
18645 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018646 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018647 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018648 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018649 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18650 if($Ndx eq "UND")
18651 { # only imported symbols
18652 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018653 }
18654 }
18655 }
18656 close(APP);
18657 }
18658 return @Imported;
18659}
18660
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018661my %ELF_BIND = map {$_=>1} (
18662 "WEAK",
18663 "GLOBAL"
18664);
18665
18666my %ELF_TYPE = map {$_=>1} (
18667 "FUNC",
18668 "IFUNC",
18669 "OBJECT",
18670 "COMMON"
18671);
18672
18673my %ELF_VIS = map {$_=>1} (
18674 "DEFAULT",
18675 "PROTECTED"
18676);
18677
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018678sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018679{ # read the line of 'readelf' output corresponding to the symbol
18680 my @Info = split(/\s+/, $_[0]);
18681 # Num: Value Size Type Bind Vis Ndx Name
18682 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018683 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018684 shift(@Info); # spaces
18685 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018686
18687 if($#Info==7)
18688 { # UND SYMBOL (N)
18689 if($Info[7]=~/\(\d+\)/) {
18690 pop(@Info);
18691 }
18692 }
18693
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018694 if($#Info!=6)
18695 { # other lines
18696 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018697 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018698 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018699 return () if(not defined $ELF_BIND{$Info[3]});
18700 return () if(not defined $ELF_VIS{$Info[4]});
18701 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18702 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18703 return ();
18704 }
18705 if($OStarget eq "symbian")
18706 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18707 if(index($Info[6], "_._.absent_export_")!=-1)
18708 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18709 return ();
18710 }
18711 $Info[6]=~s/\@.+//g; # remove version
18712 }
18713 if(index($Info[2], "0x") == 0)
18714 { # size == 0x3d158
18715 $Info[2] = hex($Info[2]);
18716 }
18717 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018718}
18719
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018720sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018721{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018722 my ($LibVersion, $Name) = @_;
18723 return "" if(not $LibVersion or not $Name);
18724 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18725 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018726 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018727 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18728}
18729
18730sub get_LibPath_I($$)
18731{
18732 my ($LibVersion, $Name) = @_;
18733 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018734 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018735 if(-f $Name)
18736 { # absolute path
18737 return $Name;
18738 }
18739 else
18740 { # broken
18741 return "";
18742 }
18743 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018744 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018745 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018746 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018747 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018748 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018749 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018750 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018751 }
18752 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18753 { # ldconfig default paths
18754 return $DefaultPath;
18755 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018756 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018757 { # search in default linker directories
18758 # and then in all system paths
18759 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018760 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761 }
18762 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018763 if(not defined $Cache{"checkSystemFiles"}) {
18764 checkSystemFiles();
18765 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018766 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18767 return $AllObjects[0];
18768 }
18769 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18770 {
18771 if($ShortName ne $Name)
18772 { # FIXME: check this case
18773 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18774 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018775 }
18776 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018777 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018778 # can't find
18779 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018780}
18781
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018782sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018783{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018784 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18785 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018786
18787 my $Real_Path = realpath($Lib_Path);
18788
18789 if(not $Real_Path)
18790 { # broken link
18791 return ();
18792 }
18793
18794 my $Lib_Name = get_filename($Real_Path);
18795
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018796 if($ExtraInfo)
18797 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018798 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018799 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018800 }
18801
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018802 if($IsNeededLib)
18803 {
18804 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18805 return ();
18806 }
18807 }
18808 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018809 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018811 push(@RecurLib, $Lib_Name);
18812 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018813 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18814
18815 if(not $IsNeededLib)
18816 { # special cases: libstdc++ and libc
18817 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18818 {
18819 if($ShortName eq "libstdc++")
18820 { # libstdc++.so.6
18821 $STDCXX_TESTING = 1;
18822 }
18823 elsif($ShortName eq "libc")
18824 { # libc-2.11.3.so
18825 $GLIBC_TESTING = 1;
18826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018827 }
18828 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018829 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018830 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018831 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018832 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018833 mkpath(get_dirname($DebugPath));
18834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018835 if($OStarget eq "macos")
18836 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018837 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018838 if(not $NM) {
18839 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018840 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018841 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018842 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018843 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018844 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018845 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018846 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018847 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018848 else
18849 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018850 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018852 while(<LIB>)
18853 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018854 if($CheckUndefined)
18855 {
18856 if(not $IsNeededLib)
18857 {
18858 if(/ U _([\w\$]+)\s*\Z/)
18859 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018860 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018861 next;
18862 }
18863 }
18864 }
18865
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018866 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018867 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018868 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018869 if($IsNeededLib)
18870 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018871 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018872 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018873 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18874 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018877 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018878 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018879 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18880 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018881 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18882 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018883 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018884 setLanguage($LibVersion, "C++");
18885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 }
18887 if($CheckObjectsOnly
18888 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018889 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018890 }
18891 }
18892 }
18893 }
18894 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018895
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018896 if($Deps)
18897 {
18898 if($LIB_TYPE eq "dynamic")
18899 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018900
18901 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018902 if(not $OtoolCmd) {
18903 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018904 }
18905
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018906 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18907 while(<LIB>)
18908 {
18909 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18910 and $1 ne $Lib_Path) {
18911 $NeededLib{$1} = 1;
18912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018913 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018914 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018916 }
18917 }
18918 elsif($OStarget eq "windows")
18919 { # Windows *.dll, *.lib
18920 my $DumpBinCmd = get_CmdPath("dumpbin");
18921 if(not $DumpBinCmd) {
18922 exitStatus("Not_Found", "can't find \"dumpbin\"");
18923 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018924 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018925 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018926 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018927 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018928 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018929 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018930 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018931 else
18932 { # write to pipe
18933 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018935 while(<LIB>)
18936 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18937 # 1198 4AD SetThreadToken (forwarded to ...)
18938 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018939 # 1 0 00005B30 ??0?N = ... (with pdb)
18940 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018941 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018942 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018943 { # dynamic, static and forwarded symbols
18944 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018945 if($IsNeededLib)
18946 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018947 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018948 {
18949 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18950 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018952 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018953 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018954 {
18955 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18956 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018957 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18958 {
18959 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18960 setLanguage($LibVersion, "C++");
18961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018962 }
18963 if($CheckObjectsOnly
18964 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018965 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018966 }
18967 }
18968 }
18969 }
18970 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018971
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018972 if($Deps)
18973 {
18974 if($LIB_TYPE eq "dynamic")
18975 { # dependencies
18976 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18977 while(<LIB>)
18978 {
18979 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18980 and $1 ne $Lib_Path) {
18981 $NeededLib{path_format($1, $OSgroup)} = 1;
18982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018983 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018984 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018986 }
18987 }
18988 else
18989 { # Unix; *.so, *.a
18990 # Symbian: *.dso, *.lib
18991 my $ReadelfCmd = get_CmdPath("readelf");
18992 if(not $ReadelfCmd) {
18993 exitStatus("Not_Found", "can't find \"readelf\"");
18994 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018995 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018996 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018997 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018998 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018999 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019000 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019001 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019002 else
19003 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019004 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019005 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019006 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 while(<LIB>)
19008 {
19009 if($LIB_TYPE eq "dynamic")
19010 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019011 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019012 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019013 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019014 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019015 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019016 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019017 # do nothing with symtab
19018 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019019 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019020 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019021 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019022 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019023 next;
19024 }
19025 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019026 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019027 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019028 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019029 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019030 if($CheckUndefined)
19031 {
19032 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019033 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019034 }
19035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019036 next;
19037 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019038 if($Bind eq "WEAK")
19039 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019040 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019041 if($Weak eq "-Weak")
19042 { # skip WEAK symbols
19043 next;
19044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019045 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019046 my $Short = $Symbol;
19047 $Short=~s/\@.+//g;
19048 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019049 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019050 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19051 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019052 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019053 if($IsNeededLib)
19054 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019055 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019056 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019057 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19058 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019061 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019062 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019063 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19064 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19065 if($Vers)
19066 {
19067 if($LIB_EXT eq "so")
19068 { # value
19069 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19070 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019072 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019073 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19074 {
19075 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19076 setLanguage($LibVersion, "C++");
19077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019078 }
19079 if($CheckObjectsOnly
19080 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019082 }
19083 }
19084 }
19085 }
19086 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019087
19088 if($Deps and $LIB_TYPE eq "dynamic")
19089 { # dynamic library specifics
19090 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19091 open(LIB, $Cmd." |");
19092
19093 while(<LIB>)
19094 {
19095 if(/NEEDED.+\[([^\[\]]+)\]/)
19096 { # dependencies:
19097 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19098 $NeededLib{$1} = 1;
19099 }
19100 }
19101
19102 close(LIB);
19103 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019104 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019105 if($Vers)
19106 {
19107 if(not $IsNeededLib and $LIB_EXT eq "so")
19108 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019109 my %Found = ();
19110
19111 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019112 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019113 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019114 next if(index($Symbol,"\@")==-1);
19115 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019116 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019117 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019118 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019119 if($Symbol_SameValue ne $Symbol
19120 and index($Symbol_SameValue,"\@")==-1)
19121 {
19122 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019123 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019124 last;
19125 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019126 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019127 }
19128 }
19129
19130 # default
19131 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19132 {
19133 next if(defined $Found{$Symbol});
19134 next if(index($Symbol,"\@\@")==-1);
19135
19136 if($Symbol=~/\A([^\@]*)\@\@/
19137 and not $SymVer{$LibVersion}{$1})
19138 {
19139 $SymVer{$LibVersion}{$1} = $Symbol;
19140 $Found{$Symbol} = 1;
19141 }
19142 }
19143
19144 # non-default
19145 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19146 {
19147 next if(defined $Found{$Symbol});
19148 next if(index($Symbol,"\@")==-1);
19149
19150 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19151 and not $SymVer{$LibVersion}{$1})
19152 {
19153 $SymVer{$LibVersion}{$1} = $Symbol;
19154 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019155 }
19156 }
19157 }
19158 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019159 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019160 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019161 foreach my $DyLib (sort keys(%NeededLib))
19162 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019163 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19164
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019165 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19166 {
19167 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19168 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19169 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171 }
19172 }
19173 pop(@RecurLib);
19174 return $Library_Symbol{$LibVersion};
19175}
19176
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019177sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019179 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019180 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 return keys(%Prefixes);
19182}
19183
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019184sub get_prefixes_I($$)
19185{
19186 foreach my $P (@{$_[0]})
19187 {
19188 my @Parts = reverse(split(/[\/\\]+/, $P));
19189 my $Name = $Parts[0];
19190 foreach (1 .. $#Parts)
19191 {
19192 $_[1]->{$Name}{$P} = 1;
19193 last if($_>4 or $Parts[$_] eq "include");
19194 $Name = $Parts[$_].$SLASH.$Name;
19195 }
19196 }
19197}
19198
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019199sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019200{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019201 $Cache{"checkSystemFiles"} = 1;
19202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019203 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019204
19205 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019206 {
19207 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019208
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019209 my @Files = cmd_find($DevelPath,"f");
19210 foreach my $Link (cmd_find($DevelPath,"l"))
19211 { # add symbolic links
19212 if(-f $Link) {
19213 push(@Files, $Link);
19214 }
19215 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019216
19217 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019218 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019219 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019220 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19221 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19222 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019223 }
19224
19225 # search for libraries in /usr/lib (including symbolic links)
19226 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19227 foreach my $Path (@Libs)
19228 {
19229 my $N = get_filename($Path);
19230 $SystemObjects{$N}{$Path} = 1;
19231 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 }
19233 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019234
19235 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019236 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019237 foreach my $DevelPath (@{$SystemPaths{"include"}})
19238 {
19239 next if(not -d $DevelPath);
19240 # search for all header files in the /usr/include
19241 # with or without extension (ncurses.h, QtCore, ...)
19242 push(@SysHeaders, cmd_find($DevelPath,"f"));
19243 foreach my $Link (cmd_find($DevelPath,"l"))
19244 { # add symbolic links
19245 if(-f $Link) {
19246 push(@SysHeaders, $Link);
19247 }
19248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019249 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019250 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251 }
19252}
19253
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019254sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019255{
19256 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019257 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019258 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19259 {
19260 if(not -e $Dest) {
19261 exitStatus("Access_Error", "can't access \'$Dest\'");
19262 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019263 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019264 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19265 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019266 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019267 }
19268 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019269 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019270}
19271
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019272sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019273{
19274 my ($Path, $LibVersion) = @_;
19275 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019276 my $Name = get_filename($Path);
19277 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019278 return 1;
19279 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019280 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019281 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19282 return 1;
19283 }
19284 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19285 {
19286 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19287 return 1;
19288 }
19289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019290 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019292 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019293 return 1;
19294 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019295 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019296 return 1;
19297 }
19298 }
19299 return 0;
19300}
19301
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019302sub specificHeader($$)
19303{
19304 my ($Header, $Spec) = @_;
19305 my $Name = get_filename($Header);
19306
19307 if($Spec eq "windows")
19308 {# MS Windows
19309 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19310 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19311 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19312 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19313 my @Dirs = (
19314 "win32",
19315 "win64",
19316 "win",
19317 "windows",
19318 "msvcrt"
19319 ); # /gsf-win32/
19320 if(my $DIRs = join("|", @Dirs)) {
19321 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19322 }
19323 }
19324 elsif($Spec eq "macos")
19325 { # Mac OS
19326 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19327 }
19328
19329 return 0;
19330}
19331
19332sub skipAlienHeader($)
19333{
19334 my $Path = $_[0];
19335 my $Name = get_filename($Path);
19336 my $Dir = get_dirname($Path);
19337
19338 if($Tolerance=~/2/)
19339 { # 2 - skip internal headers
19340 my @Terms = (
19341 "p",
19342 "priv",
19343 "int",
19344 "impl",
19345 "implementation",
19346 "internal",
19347 "private",
19348 "old",
19349 "compat",
19350 "debug",
19351 "test",
19352 "gen"
19353 );
19354
19355 my @Dirs = (
19356 "private",
19357 "priv",
19358 "port",
19359 "impl",
19360 "internal",
19361 "detail",
19362 "details",
19363 "old",
19364 "compat",
19365 "debug",
19366 "config",
19367 "compiler",
19368 "platform",
19369 "test"
19370 );
19371
19372 if(my $TERMs = join("|", @Terms)) {
19373 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19374 }
19375 if(my $DIRs = join("|", @Dirs)) {
19376 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19377 }
19378
19379 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19380 }
19381
19382 if($Tolerance=~/1/)
19383 { # 1 - skip non-Linux headers
19384 if($OSgroup ne "windows")
19385 {
19386 if(specificHeader($Path, "windows")) {
19387 return 1;
19388 }
19389 }
19390 if($OSgroup ne "macos")
19391 {
19392 if(specificHeader($Path, "macos")) {
19393 return 1;
19394 }
19395 }
19396 }
19397
19398 # valid
19399 return 0;
19400}
19401
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019402sub skipHeader($$)
19403{
19404 my ($Path, $LibVersion) = @_;
19405 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019406 if(defined $Cache{"skipHeader"}{$Path}) {
19407 return $Cache{"skipHeader"}{$Path};
19408 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019409 if(defined $Tolerance and $Tolerance=~/1|2/)
19410 { # --tolerant
19411 if(skipAlienHeader($Path)) {
19412 return ($Cache{"skipHeader"}{$Path} = 1);
19413 }
19414 }
19415 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19416 return 0;
19417 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019418 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19419}
19420
19421sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019422{ # returns:
19423 # 1 - if header should NOT be included and checked
19424 # 2 - if header should NOT be included, but should be checked
19425 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019426 my $Name = get_filename($Path);
19427 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019428 return $Kind;
19429 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019430 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19431 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 if(index($Path, $D)!=-1)
19434 {
19435 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19436 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019438 }
19439 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019440 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19441 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019443 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19444 {
19445 if($Name=~/$P/) {
19446 return $Kind;
19447 }
19448 if($P=~/[\/\\]/ and $Path=~/$P/) {
19449 return $Kind;
19450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451 }
19452 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019454 return 0;
19455}
19456
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019457sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019458{
19459 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019460 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019461 { # system directory
19462 return;
19463 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019464 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019465 { # already registered
19466 return;
19467 }
19468 foreach my $Path (find_libs($Dir,"",1))
19469 {
19470 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019471 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019472 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019473 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019474 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19475}
19476
19477sub registerObject($$)
19478{
19479 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019480
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019481 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019482 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019483 if($OSgroup=~/linux|bsd/i)
19484 {
19485 if(my $SONAME = getSONAME($Path)) {
19486 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19487 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019488 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019489 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19490 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019491 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019492
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019493 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019494 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019495 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019496 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019497 if($ObjArch ne getArch_GCC($LibVersion))
19498 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19499 $CheckedArch{$LibVersion} = 1;
19500 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 +040019501 }
19502 }
19503 }
19504}
19505
19506sub getArch_Object($)
19507{
19508 my $Path = $_[0];
19509
19510 my %MachineType = (
19511 "14C" => "x86",
19512 "8664" => "x86_64",
19513 "1C0" => "arm",
19514 "200" => "ia64"
19515 );
19516
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019517 my %ArchName = (
19518 "s390:31-bit" => "s390",
19519 "s390:64-bit" => "s390x",
19520 "powerpc:common" => "ppc32",
19521 "powerpc:common64" => "ppc64",
19522 "i386:x86-64" => "x86_64",
19523 "mips:3000" => "mips",
19524 "sparc:v8plus" => "sparcv9"
19525 );
19526
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019527 if($OSgroup eq "windows")
19528 {
19529 my $DumpbinCmd = get_CmdPath("dumpbin");
19530 if(not $DumpbinCmd) {
19531 exitStatus("Not_Found", "can't find \"dumpbin\"");
19532 }
19533
19534 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19535 my $Out = `$Cmd`;
19536
19537 if($Out=~/(\w+)\smachine/)
19538 {
19539 if(my $Type = $MachineType{uc($1)})
19540 {
19541 return $Type;
19542 }
19543 }
19544 }
19545 elsif($OSgroup=~/linux|bsd/)
19546 {
19547 my $ObjdumpCmd = get_CmdPath("objdump");
19548 if(not $ObjdumpCmd) {
19549 exitStatus("Not_Found", "can't find \"objdump\"");
19550 }
19551
19552 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
19553 my $Out = `$Cmd`;
19554
19555 if($Out=~/architecture:\s+([\w\-\:]+)/)
19556 {
19557 my $Arch = $1;
19558 if($Arch=~s/\:(.+)//)
19559 {
19560 my $Suffix = $1;
19561
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019562 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019563 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019564 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019565 }
19566 }
19567
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019568 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019569 $Arch = "x86";
19570 }
19571
19572 if($Arch eq "x86-64") {
19573 $Arch = "x86_64";
19574 }
19575
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019576 if($Arch eq "ia64-elf64") {
19577 $Arch = "ia64";
19578 }
19579
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019580 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019581 }
19582 }
19583 else
19584 { # macos, etc.
19585 # TODO
19586 }
19587
19588 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019589}
19590
19591sub getSONAME($)
19592{
19593 my $Path = $_[0];
19594 return if(not $Path);
19595 if(defined $Cache{"getSONAME"}{$Path}) {
19596 return $Cache{"getSONAME"}{$Path};
19597 }
19598 my $ObjdumpCmd = get_CmdPath("objdump");
19599 if(not $ObjdumpCmd) {
19600 exitStatus("Not_Found", "can't find \"objdump\"");
19601 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019602 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019603 if($OSgroup eq "windows") {
19604 $SonameCmd .= " | find \"SONAME\"";
19605 }
19606 else {
19607 $SonameCmd .= " | grep SONAME";
19608 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019609 if(my $SonameInfo = `$SonameCmd`)
19610 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019611 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19612 return ($Cache{"getSONAME"}{$Path} = $1);
19613 }
19614 }
19615 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019616}
19617
19618sub getSOPaths_Dest($$)
19619{
19620 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019621 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019622 return ();
19623 }
19624 if(-f $Dest)
19625 {
19626 if(not parse_libname($Dest, "name", $OStarget)) {
19627 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19628 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019629 registerObject($Dest, $LibVersion);
19630 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631 return ($Dest);
19632 }
19633 elsif(-d $Dest)
19634 {
19635 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019636 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019637 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019638 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19639 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019640 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019641 { # all files and symlinks that match the name of a library
19642 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19643 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019644 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019645 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019646 }
19647 }
19648 }
19649 else
19650 { # search for all files and symlinks
19651 foreach my $Path (find_libs($Dest,"",""))
19652 {
19653 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019654 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019655 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019656 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019657 }
19658 if($OSgroup eq "macos")
19659 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019660 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019661 {
19662 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019663 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019664 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019665 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19666 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019667 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019668 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019669 }
19670 }
19671 }
19672 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019673 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019674 }
19675 else {
19676 return ();
19677 }
19678}
19679
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019680sub isCyclical($$)
19681{
19682 my ($Stack, $Value) = @_;
19683 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019684}
19685
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019686sub getGCC_Opts($)
19687{ # to use in module
19688 my $LibVersion = $_[0];
19689
19690 my @Opts = ();
19691
19692 if($CompilerOptions{$LibVersion})
19693 { # user-defined options
19694 push(@Opts, $CompilerOptions{$LibVersion});
19695 }
19696 if($GccOptions)
19697 { # additional
19698 push(@Opts, $GccOptions);
19699 }
19700
19701 if(@Opts) {
19702 return join(" ", @Opts);
19703 }
19704
19705 return undef;
19706}
19707
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019708sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019709{
19710 my $LibVersion = $_[0];
19711
19712 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19713 return $Cache{"getArch_GCC"}{$LibVersion};
19714 }
19715
19716 my $Arch = undef;
19717
19718 if($GCC_PATH)
19719 {
19720 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19721
19722 my $Cmd = $GCC_PATH." test.c -o test";
19723 if(my $Opts = getGCC_Opts($LibVersion))
19724 { # user-defined options
19725 $Cmd .= " ".$Opts;
19726 }
19727
19728 chdir($TMP_DIR);
19729 system($Cmd);
19730 chdir($ORIG_DIR);
19731
19732 $Arch = getArch_Object("$TMP_DIR/test");
19733
19734 unlink("$TMP_DIR/test.c");
19735 unlink("$TMP_DIR/test");
19736 }
19737
19738 if(not $Arch) {
19739 exitStatus("Error", "can't check ARCH type");
19740 }
19741
19742 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19743}
19744
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019745sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019746{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019747 my $LibVersion = $_[0];
19748
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019749 my $Size = undef;
19750
19751 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019752 if(my $Arch = getArch($LibVersion))
19753 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019754 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019755 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019756 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019757 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19758 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019759 }
19760 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019761
19762 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019763 {
19764 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019765
19766 my $Cmd = $GCC_PATH." -E -dD empty.h";
19767 if(my $Opts = getGCC_Opts($LibVersion))
19768 { # user-defined options
19769 $Cmd .= " ".$Opts;
19770 }
19771
19772 chdir($TMP_DIR);
19773 my $Defines = `$Cmd`;
19774 chdir($ORIG_DIR);
19775
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019776 unlink("$TMP_DIR/empty.h");
19777
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019778 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19779 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019780 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019781 }
19782 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19783 { # GCC 3
19784 my $PTRDIFF = $1;
19785 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019786 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019787 }
19788 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019789 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019790 }
19791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019792 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019793
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019794 if(not $Size) {
19795 exitStatus("Error", "can't check WORD size");
19796 }
19797
19798 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799}
19800
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019801sub getWordSize($)
19802{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019803 return $WORD_SIZE{$_[0]};
19804}
19805
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019806sub majorVersion($)
19807{
19808 my $V = $_[0];
19809 return 0 if(not $V);
19810 my @VParts = split(/\./, $V);
19811 return $VParts[0];
19812}
19813
19814sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019815{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019816 my ($V1, $V2) = @_;
19817 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 my @V1Parts = split(/\./, $V1);
19819 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019820 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19821 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019822 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19823 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19824 }
19825 return -1 if($#V1Parts < $#V2Parts);
19826 return 1 if($#V1Parts > $#V2Parts);
19827 return 0;
19828}
19829
19830sub read_ABI_Dump($$)
19831{
19832 my ($LibVersion, $Path) = @_;
19833 return if(not $LibVersion or not -e $Path);
19834 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019835 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019836 { # input *.abi
19837 $FilePath = $Path;
19838 }
19839 else
19840 { # input *.abi.tar.gz
19841 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019842 if(not isDump_U($FilePath)) {
19843 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019845 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019846
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019847 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019848
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019849 my $Line = readLineNum($FilePath, 0);
19850 if($Line=~/xml/)
19851 { # XML format
19852 loadModule("XmlDump");
19853 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019854 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019855 else
19856 { # Perl Data::Dumper format (default)
19857 open(DUMP, $FilePath);
19858 local $/ = undef;
19859 my $Content = <DUMP>;
19860 close(DUMP);
19861
19862 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19863 { # remove temp file
19864 unlink($FilePath);
19865 }
19866 if($Content!~/};\s*\Z/) {
19867 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19868 }
19869 $ABI = eval($Content);
19870 if(not $ABI) {
19871 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019873 }
19874 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019875 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019876 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019877 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019878 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019879 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019880 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019881 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019882 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019883
19884 if($ABI->{"ABI_DUMP_VERSION"})
19885 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019886 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019887 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019888 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019889 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019890 }
19891 else
19892 { # support for old ABI dumps
19893 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019894 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019895 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019896 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019897 }
19898 if(majorVersion($DVersion)<2)
19899 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019900 if($UseOldDumps)
19901 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019902 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19903 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019904 }
19905 }
19906 else
19907 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019908 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019909 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019910 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019911 }
19912 exitStatus("Dump_Version", $Msg);
19913 }
19914 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019915
19916 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19917 { # DWARF ABI Dump
19918 $UseConv_Real{$LibVersion}{"P"} = 1;
19919 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19920
19921 $UsedDump{$LibVersion}{"DWARF"} = 1;
19922
19923 $TargetComponent = "module";
19924 }
19925
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019926 if(not checkDump($LibVersion, "2.11"))
19927 { # old ABI dumps
19928 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019929 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019930 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019931 { # ABI dump created with --binary option
19932 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19933 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019934 else
19935 { # default
19936 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19937 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019938
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019939 if(defined $ABI->{"Mode"}
19940 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019941 { # --ext option
19942 $ExtendedCheck = 1;
19943 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019944 if($ABI->{"Extra"}) {
19945 $ExtraDump = 1;
19946 }
19947
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019948 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019949 {
19950 $UsedDump{$LibVersion}{"L"} = $Lang;
19951 setLanguage($LibVersion, $Lang);
19952 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019953 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019954 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019955 }
19956 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019957 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019958 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019959 if(not $TInfo)
19960 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019961 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019962 }
19963 my %Tid_TDid = ();
19964 foreach my $TDid (keys(%{$TInfo}))
19965 {
19966 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19967 {
19968 $MAX_ID = $Tid if($Tid>$MAX_ID);
19969 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019970 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019971 }
19972 }
19973 my %NewID = ();
19974 foreach my $Tid (keys(%Tid_TDid))
19975 {
19976 my @TDids = keys(%{$Tid_TDid{$Tid}});
19977 if($#TDids>=1)
19978 {
19979 foreach my $TDid (@TDids)
19980 {
19981 if($TDid) {
19982 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19983 }
19984 else
19985 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019986 my $ID = ++$MAX_ID;
19987
19988 $NewID{$TDid}{$Tid} = $ID;
19989 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19990 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019991 }
19992 }
19993 }
19994 else
19995 {
19996 my $TDid = $TDids[0];
19997 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19998 }
19999 }
20000 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20001 {
20002 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20003 if(defined $Info{"BaseType"})
20004 {
20005 my $Bid = $Info{"BaseType"}{"Tid"};
20006 my $BDid = $Info{"BaseType"}{"TDid"};
20007 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020008 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020009 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20010 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20011 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020012 }
20013 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020015 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020016 read_Machine_DumpInfo($ABI, $LibVersion);
20017 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020018 if(not $SymbolInfo{$LibVersion})
20019 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020020 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020021 }
20022 if(not keys(%{$SymbolInfo{$LibVersion}}))
20023 { # validation of old-version dumps
20024 if(not $ExtendedCheck) {
20025 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20026 }
20027 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020028 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020029 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020030 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020031 else
20032 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020033 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020034 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020035 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020036 }
20037 if(not $DepSymbols)
20038 { # Cannot reconstruct DepSymbols. This may result in false
20039 # positives if the old dump is for library 2. Not a problem if
20040 # old dumps are only from old libraries.
20041 $DepSymbols = {};
20042 }
20043 foreach my $Symbol (keys(%{$DepSymbols})) {
20044 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020046 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020047 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020048
20049 if(my $V = $TargetVersion{$LibVersion}) {
20050 $Descriptor{$LibVersion}{"Version"} = $V;
20051 }
20052 else {
20053 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20054 }
20055
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020056 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020057 if(not $SkipTypes{$LibVersion})
20058 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020059 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020060 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020061
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020062 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020063 { # if not defined by -skip-symbols option
20064 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20065 if(not $SkipSymbols{$LibVersion})
20066 { # support for old dumps
20067 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20068 }
20069 if(not $SkipSymbols{$LibVersion})
20070 { # support for old dumps
20071 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020073 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020074 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020075
20076 if(not $TargetHeaders{$LibVersion})
20077 { # if not defined by -headers-list option
20078 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20079 }
20080
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020081 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020082 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020083 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020084 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020085 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020086 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020087 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020088 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020089 if(not checkDump($LibVersion, "2.10.1")
20090 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020091 { # support for old ABI dumps: added target headers
20092 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020093 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020094 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020095 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020096 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020098 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020099 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020100 if(defined $ABI->{"GccConstants"})
20101 { # 3.0
20102 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20103 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20104 }
20105 }
20106
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020107 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020108 if(not $NestedNameSpaces{$LibVersion})
20109 { # support for old dumps
20110 # Cannot reconstruct NameSpaces. This may affect design
20111 # of the compatibility report.
20112 $NestedNameSpaces{$LibVersion} = {};
20113 }
20114 # target system type
20115 # needed to adopt HTML report
20116 if(not $DumpSystem)
20117 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020118 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020119 }
20120 # recreate environment
20121 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20122 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020123 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020125 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20126 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020127 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020128 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020129 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020130 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20131 {
20132 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20133 setLanguage($LibVersion, "C++");
20134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020135 }
20136 }
20137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020138 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20139 {
20140 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20141 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20142 }
20143 }
20144
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020145 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020146 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020147 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020148 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020149 {
20150 if(not $Symbol_Library{$LibVersion}{$MnglName}
20151 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20152 push(@VFunc, $MnglName);
20153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020154 }
20155 }
20156 translateSymbols(@VFunc, $LibVersion);
20157 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020158 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20159
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020160 if(not checkDump($LibVersion, "3.0"))
20161 { # support for old ABI dumps
20162 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20163 {
20164 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20165 {
20166 if(ref($BaseType) eq "HASH") {
20167 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20168 }
20169 }
20170 }
20171 }
20172
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020173 if(not checkDump($LibVersion, "3.2"))
20174 { # support for old ABI dumps
20175 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20176 {
20177 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20178 {
20179 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20180 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20181 }
20182 }
20183 }
20184
20185 # repair target headers list
20186 delete($TargetHeaders{$LibVersion});
20187 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020188 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20189 }
20190 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20191 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020192 }
20193
20194 # non-target constants from anon enums
20195 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20196 {
20197 if(not $ExtraDump
20198 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20199 {
20200 delete($Constants{$LibVersion}{$Name});
20201 }
20202 }
20203 }
20204
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020205 if(not checkDump($LibVersion, "2.20"))
20206 { # support for old ABI dumps
20207 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20208 {
20209 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20210
20211 if($TType=~/Struct|Union|Enum|Typedef/)
20212 { # repair complex types first
20213 next;
20214 }
20215
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020216 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020217 {
20218 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20219 if($BType=~/Struct|Union|Enum/i)
20220 {
20221 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20222 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20223 }
20224 }
20225 }
20226 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20227 {
20228 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20229 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20230 if($TType=~/Struct|Union|Enum/) {
20231 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20232 }
20233 }
20234 }
20235
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020236 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020237 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020238 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20239 { # support for old ABI dumps < 2.0 (ACC 1.22)
20240 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20241 {
20242 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20243 {
20244 if($Access ne "public") {
20245 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20246 }
20247 }
20248 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20249 }
20250 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20251 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020252 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20253 { # support for old ABI dumps
20254 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20255 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020256 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20257 { # DWARF ABI Dumps
20258 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20259 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020260 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20261 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020263 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20264 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020265 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020266 foreach (keys(%{$TInfo{"Base"}})) {
20267 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020269 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020270 if($TInfo{"Type"} eq "MethodPtr")
20271 {
20272 if(defined $TInfo{"Param"})
20273 { # support for old ABI dumps <= 1.17
20274 if(not defined $TInfo{"Param"}{"0"})
20275 {
20276 my $Max = keys(%{$TInfo{"Param"}});
20277 foreach my $Pos (1 .. $Max) {
20278 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20279 }
20280 delete($TInfo{"Param"}{$Max});
20281 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20282 }
20283 }
20284 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020285 if($TInfo{"BaseType"} eq $TypeId)
20286 { # fix ABI dump
20287 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20288 }
20289 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020290 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020291 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020292 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020293 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20294 if(not $BName)
20295 { # broken type
20296 next;
20297 }
20298 if($TInfo{"Name"} eq $BName)
20299 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020300 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020301 next;
20302 }
20303 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20304 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020305 }
20306 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020307 }
20308 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20309 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020310 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020311 }
20312 }
20313
20314 if(not checkDump($LibVersion, "2.15"))
20315 { # support for old ABI dumps
20316 my %Dups = ();
20317 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20318 {
20319 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020320 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020321 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20322 { # remove template decls
20323 delete($SymbolInfo{$LibVersion}{$InfoId});
20324 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020326 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020327 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20328 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020329 { # templates
20330 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020331 }
20332 }
20333 }
20334
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020335 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20336 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020337 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20338 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20339 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20340 { # support for old ABI dumps (< 3.1)
20341 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20342 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20343 { # add "this" first parameter
20344 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20345 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20346
20347 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20348 {
20349 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20350 foreach my $Pos (reverse(0 .. $#Pos)) {
20351 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20352 }
20353 }
20354 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20355 }
20356 }
20357
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020358 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20359 { # ABI dumps have no mangled names for C-functions
20360 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20361 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020362 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20363 { # support for old ABI dumps
20364 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20365 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020366 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20367 { # DWARF ABI Dumps
20368 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20369 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020370 }
20371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020372 $Descriptor{$LibVersion}{"Dump"} = 1;
20373}
20374
20375sub read_Machine_DumpInfo($$)
20376{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020377 my ($ABI, $LibVersion) = @_;
20378 if($ABI->{"Arch"}) {
20379 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020380 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020381 if($ABI->{"WordSize"}) {
20382 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020383 }
20384 else
20385 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020386 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 }
20388 if(not $WORD_SIZE{$LibVersion})
20389 { # support for old dumps (<1.23)
20390 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20391 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020392 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020393 }
20394 else
20395 {
20396 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020397 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020399 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20400 { # any "pointer"-type
20401 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020402 last;
20403 }
20404 }
20405 if($PSize)
20406 { # a pointer type size
20407 $WORD_SIZE{$LibVersion} = $PSize;
20408 }
20409 else {
20410 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20411 }
20412 }
20413 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020414 if($ABI->{"GccVersion"}) {
20415 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020416 }
20417}
20418
20419sub read_Libs_DumpInfo($$)
20420{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020421 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020422 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20423 if(not $Library_Symbol{$LibVersion})
20424 { # support for old dumps
20425 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020427 if(keys(%{$Library_Symbol{$LibVersion}})
20428 and not $DumpAPI) {
20429 $Descriptor{$LibVersion}{"Libs"} = "OK";
20430 }
20431}
20432
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020433sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020434{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020435 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020436
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020437 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020438 and not $DumpAPI) {
20439 $Descriptor{$LibVersion}{"Headers"} = "OK";
20440 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020441 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020442 { # headers info is stored in the old dumps in the different way
20443 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020444 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020445 { # support for old dumps: headers info corrected in 1.22
20446 $Identity = $Name;
20447 }
20448 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020449 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020450 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020451
20452 if(keys(%{$ABI->{"Sources"}})
20453 and not $DumpAPI) {
20454 $Descriptor{$LibVersion}{"Sources"} = "OK";
20455 }
20456 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20457 { # headers info is stored in the old dumps in the different way
20458 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20459 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461}
20462
20463sub find_libs($$$)
20464{
20465 my ($Path, $Type, $MaxDepth) = @_;
20466 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020467 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020468}
20469
20470sub createDescriptor($$)
20471{
20472 my ($LibVersion, $Path) = @_;
20473 if(not $LibVersion or not $Path
20474 or not -e $Path) {
20475 return "";
20476 }
20477 if(-d $Path)
20478 { # directory with headers files and shared objects
20479 return "
20480 <version>
20481 ".$TargetVersion{$LibVersion}."
20482 </version>
20483
20484 <headers>
20485 $Path
20486 </headers>
20487
20488 <libs>
20489 $Path
20490 </libs>";
20491 }
20492 else
20493 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020494 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020495 { # standard XML-descriptor
20496 return readFile($Path);
20497 }
20498 elsif(is_header($Path, 2, $LibVersion))
20499 { # header file
20500 return "
20501 <version>
20502 ".$TargetVersion{$LibVersion}."
20503 </version>
20504
20505 <headers>
20506 $Path
20507 </headers>
20508
20509 <libs>
20510 none
20511 </libs>";
20512 }
20513 elsif(parse_libname($Path, "name", $OStarget))
20514 { # shared object
20515 return "
20516 <version>
20517 ".$TargetVersion{$LibVersion}."
20518 </version>
20519
20520 <headers>
20521 none
20522 </headers>
20523
20524 <libs>
20525 $Path
20526 </libs>";
20527 }
20528 else
20529 { # standard XML-descriptor
20530 return readFile($Path);
20531 }
20532 }
20533}
20534
20535sub detect_lib_default_paths()
20536{
20537 my %LPaths = ();
20538 if($OSgroup eq "bsd")
20539 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020540 if(my $LdConfig = get_CmdPath("ldconfig"))
20541 {
20542 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20543 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020544 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20545 {
20546 my $Name = "lib".$1;
20547 if(not defined $LPaths{$Name}) {
20548 $LPaths{$Name} = $2;
20549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020550 }
20551 }
20552 }
20553 else {
20554 printMsg("WARNING", "can't find ldconfig");
20555 }
20556 }
20557 else
20558 {
20559 if(my $LdConfig = get_CmdPath("ldconfig"))
20560 {
20561 if($SystemRoot and $OSgroup eq "linux")
20562 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20563 if(-e $SystemRoot."/etc/ld.so.conf") {
20564 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20565 }
20566 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020567 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20568 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020569 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20570 {
20571 my ($Name, $Path) = ($1, $2);
20572 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020573 if(not defined $LPaths{$Name})
20574 { # get first element from the list of available paths
20575
20576 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20577 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20578 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20579
20580 $LPaths{$Name} = $Path;
20581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020582 }
20583 }
20584 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020585 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020586 printMsg("WARNING", "can't find ldconfig");
20587 }
20588 }
20589 return \%LPaths;
20590}
20591
20592sub detect_bin_default_paths()
20593{
20594 my $EnvPaths = $ENV{"PATH"};
20595 if($OSgroup eq "beos") {
20596 $EnvPaths.=":".$ENV{"BETOOLS"};
20597 }
20598 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020599 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020600 {
20601 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020602 next if(not $Path);
20603 if($SystemRoot
20604 and $Path=~/\A\Q$SystemRoot\E\//)
20605 { # do NOT use binaries from target system
20606 next;
20607 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020608 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020609 }
20610}
20611
20612sub detect_inc_default_paths()
20613{
20614 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020615 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020616 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020617 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020618 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020619 next if(index($Line, "/cc1plus ")!=-1);
20620
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020621 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20622 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020623 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020624 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020625 if(index($Path, "c++")!=-1
20626 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020627 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020628 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020629 if(not defined $MAIN_CPP_DIR
20630 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20631 $MAIN_CPP_DIR = $Path;
20632 }
20633 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020634 elsif(index($Path, "gcc")!=-1) {
20635 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020636 }
20637 else
20638 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020639 if($Path=~/local[\/\\]+include/)
20640 { # local paths
20641 next;
20642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020643 if($SystemRoot
20644 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20645 { # The GCC include path for user headers is not a part of the system root
20646 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20647 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20648 next;
20649 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020650 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020651 }
20652 }
20653 }
20654 unlink("$TMP_DIR/empty.h");
20655 return %DPaths;
20656}
20657
20658sub detect_default_paths($)
20659{
20660 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20661 my $Search = $_[0];
20662 if($Search!~/inc/) {
20663 $HSearch = 0;
20664 }
20665 if($Search!~/lib/) {
20666 $LSearch = 0;
20667 }
20668 if($Search!~/bin/) {
20669 $BSearch = 0;
20670 }
20671 if($Search!~/gcc/) {
20672 $GSearch = 0;
20673 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020674 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020675 { # <search_headers> section of the XML descriptor
20676 # do NOT search for systems headers
20677 $HSearch = 0;
20678 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020679 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020680 { # <search_headers> section of the XML descriptor
20681 # do NOT search for systems headers
20682 $LSearch = 0;
20683 }
20684 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20685 { # additional search paths
20686 next if($Type eq "include" and not $HSearch);
20687 next if($Type eq "lib" and not $LSearch);
20688 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020689 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020690 }
20691 if($OSgroup ne "windows")
20692 { # unix-like
20693 foreach my $Type ("include", "lib", "bin")
20694 { # automatic detection of system "devel" directories
20695 next if($Type eq "include" and not $HSearch);
20696 next if($Type eq "lib" and not $LSearch);
20697 next if($Type eq "bin" and not $BSearch);
20698 my ($UsrDir, $RootDir) = ("/usr", "/");
20699 if($SystemRoot and $Type ne "bin")
20700 { # 1. search for target headers and libraries
20701 # 2. use host commands: ldconfig, readelf, etc.
20702 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20703 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020704 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020705 if(-d $RootDir."/".$Type)
20706 { # if "/lib" is symbolic link
20707 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020708 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020709 }
20710 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020711 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020712 }
20713 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020714 if(-d $UsrDir)
20715 {
20716 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020717 if(-d $UsrDir."/".$Type)
20718 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020719 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020720 }
20721 }
20722 }
20723 }
20724 if($BSearch)
20725 {
20726 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020727 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020728 }
20729 # check environment variables
20730 if($OSgroup eq "beos")
20731 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020732 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020733 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020734 if($_ eq ".") {
20735 next;
20736 }
20737 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20738 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20739 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020740 }
20741 }
20742 if($HSearch)
20743 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020744 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20745 split(/:|;/, $ENV{"BEINCLUDES"})
20746 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020747 }
20748 if($LSearch)
20749 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020750 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20751 split(/:|;/, $ENV{"BELIBRARIES"}),
20752 split(/:|;/, $ENV{"LIBRARY_PATH"})
20753 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020754 }
20755 }
20756 if($LSearch)
20757 { # using linker to get system paths
20758 if(my $LPaths = detect_lib_default_paths())
20759 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020760 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020761 foreach my $Name (keys(%{$LPaths}))
20762 {
20763 if($SystemRoot
20764 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20765 { # wrong ldconfig configuration
20766 # check your <sysroot>/etc/ld.so.conf
20767 next;
20768 }
20769 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020770 if(my $Dir = get_dirname($LPaths->{$Name})) {
20771 $Dirs{$Dir} = 1;
20772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020773 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020774 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020775 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020776 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020777 }
20778 if($BSearch)
20779 {
20780 if($CrossGcc)
20781 { # --cross-gcc=arm-linux-gcc
20782 if(-e $CrossGcc)
20783 { # absolute or relative path
20784 $GCC_PATH = get_abs_path($CrossGcc);
20785 }
20786 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20787 { # command name
20788 $GCC_PATH = $CrossGcc;
20789 }
20790 else {
20791 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20792 }
20793 if($GCC_PATH=~/\s/) {
20794 $GCC_PATH = "\"".$GCC_PATH."\"";
20795 }
20796 }
20797 }
20798 if($GSearch)
20799 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020800 if(not $CrossGcc)
20801 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020802 $GCC_PATH = get_CmdPath("gcc");
20803 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020804 if(not $GCC_PATH)
20805 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020806 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020807 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020808 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020809 { # select the latest version
20810 @GCCs = sort {$b cmp $a} @GCCs;
20811 if(check_gcc($GCCs[0], "3"))
20812 {
20813 $GCC_PATH = $GCCs[0];
20814 last;
20815 }
20816 }
20817 }
20818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020819 if(not $GCC_PATH) {
20820 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20821 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020823 if(not $CheckObjectsOnly_Opt)
20824 {
20825 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20826 {
20827 my $GccTarget = get_dumpmachine($GCC_PATH);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020828 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020829 if($GccTarget=~/symbian/)
20830 {
20831 $OStarget = "symbian";
20832 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20833 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020834
20835 # check GCC version
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020836 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020837 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040020838 # introduced in 4.8
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020839 # fixed in 4.8.3
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020840 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20841 $EMERGENCY_MODE_48 = 1;
20842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020843 }
20844 else {
20845 exitStatus("Error", "something is going wrong with the GCC compiler");
20846 }
20847 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020848 if($HSearch)
20849 {
20850 if(not $NoStdInc)
20851 { # do NOT search in GCC standard paths
20852 my %DPaths = detect_inc_default_paths();
20853 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20854 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20855 @DefaultIncPaths = @{$DPaths{"Inc"}};
20856 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020857 }
20858 }
20859 }
20860 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020861 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020862 my $IncPath = "/usr/include";
20863 if($SystemRoot) {
20864 $IncPath = $SystemRoot.$IncPath;
20865 }
20866 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020867 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020868 }
20869 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020870
20871 if($ExtraInfo)
20872 {
20873 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20874 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020876}
20877
20878sub getLIB_EXT($)
20879{
20880 my $Target = $_[0];
20881 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20882 return $Ext;
20883 }
20884 return $OS_LibExt{$LIB_TYPE}{"default"};
20885}
20886
20887sub getAR_EXT($)
20888{
20889 my $Target = $_[0];
20890 if(my $Ext = $OS_Archive{$Target}) {
20891 return $Ext;
20892 }
20893 return $OS_Archive{"default"};
20894}
20895
20896sub get_dumpversion($)
20897{
20898 my $Cmd = $_[0];
20899 return "" if(not $Cmd);
20900 if($Cache{"get_dumpversion"}{$Cmd}) {
20901 return $Cache{"get_dumpversion"}{$Cmd};
20902 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020903 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020904 chomp($V);
20905 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20906}
20907
20908sub get_dumpmachine($)
20909{
20910 my $Cmd = $_[0];
20911 return "" if(not $Cmd);
20912 if($Cache{"get_dumpmachine"}{$Cmd}) {
20913 return $Cache{"get_dumpmachine"}{$Cmd};
20914 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020915 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020916 chomp($Machine);
20917 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20918}
20919
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020920sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020921{
20922 my $Cmd = $_[0];
20923 return "" if(not $Cmd);
20924 my @Options = (
20925 "--version",
20926 "-help"
20927 );
20928 foreach my $Opt (@Options)
20929 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020930 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020931 if($Info) {
20932 return 1;
20933 }
20934 }
20935 return 0;
20936}
20937
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020938sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020939{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020940 my ($Cmd, $ReqVer) = @_;
20941 return 0 if(not $Cmd or not $ReqVer);
20942 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20943 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020944 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020945 if(my $GccVer = get_dumpversion($Cmd))
20946 {
20947 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20948 if(cmpVersions($GccVer, $ReqVer)>=0) {
20949 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20950 }
20951 }
20952 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953}
20954
20955sub get_depth($)
20956{
20957 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020958 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020959 }
20960 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20961}
20962
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020963sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020964{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020965 return if($Cache{"registerGccHeaders"}); # this function should be called once
20966
20967 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020968 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020969 my @Headers = cmd_find($Path,"f");
20970 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20971 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020972 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020973 my $FileName = get_filename($HPath);
20974 if(not defined $DefaultGccHeader{$FileName})
20975 { # skip duplicated
20976 $DefaultGccHeader{$FileName} = $HPath;
20977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020978 }
20979 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020980 $Cache{"registerGccHeaders"} = 1;
20981}
20982
20983sub registerCppHeaders()
20984{
20985 return if($Cache{"registerCppHeaders"}); # this function should be called once
20986
20987 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020988 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020989 my @Headers = cmd_find($CppDir,"f");
20990 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20991 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020992 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020993 my $FileName = get_filename($Path);
20994 if(not defined $DefaultCppHeader{$FileName})
20995 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020996 $DefaultCppHeader{$FileName} = $Path;
20997 }
20998 }
20999 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021000 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021001}
21002
21003sub parse_libname($$$)
21004{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021005 return "" if(not $_[0]);
21006 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21007 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021008 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021009 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21010}
21011
21012sub parse_libname_I($$$)
21013{
21014 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021015
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021016 if($Target eq "symbian") {
21017 return parse_libname_symbian($Name, $Type);
21018 }
21019 elsif($Target eq "windows") {
21020 return parse_libname_windows($Name, $Type);
21021 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021022
21023 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021024 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021025 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021026 { # libSDL-1.2.so.0.7.1
21027 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021028 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021029 if($Type eq "name")
21030 { # libSDL-1.2
21031 # libwbxml2
21032 return $2;
21033 }
21034 elsif($Type eq "name+ext")
21035 { # libSDL-1.2.so
21036 # libwbxml2.so
21037 return $1;
21038 }
21039 elsif($Type eq "version")
21040 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021041 if(defined $7
21042 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021043 { # 0.7.1
21044 return $7;
21045 }
21046 else
21047 { # libc-2.5.so (=>2.5 version)
21048 my $MV = $5;
21049 $MV=~s/\A[\-\_]+//g;
21050 return $MV;
21051 }
21052 }
21053 elsif($Type eq "short")
21054 { # libSDL
21055 # libwbxml2
21056 return $3;
21057 }
21058 elsif($Type eq "shortest")
21059 { # SDL
21060 # wbxml
21061 return shortest_name($3);
21062 }
21063 }
21064 return "";# error
21065}
21066
21067sub parse_libname_symbian($$)
21068{
21069 my ($Name, $Type) = @_;
21070 my $Ext = getLIB_EXT("symbian");
21071 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21072 { # libpthread{00010001}.dso
21073 if($Type eq "name")
21074 { # libpthread{00010001}
21075 return $2;
21076 }
21077 elsif($Type eq "name+ext")
21078 { # libpthread{00010001}.dso
21079 return $1;
21080 }
21081 elsif($Type eq "version")
21082 { # 00010001
21083 my $V = $4;
21084 $V=~s/\{(.+)\}/$1/;
21085 return $V;
21086 }
21087 elsif($Type eq "short")
21088 { # libpthread
21089 return $3;
21090 }
21091 elsif($Type eq "shortest")
21092 { # pthread
21093 return shortest_name($3);
21094 }
21095 }
21096 return "";# error
21097}
21098
21099sub parse_libname_windows($$)
21100{
21101 my ($Name, $Type) = @_;
21102 my $Ext = getLIB_EXT("windows");
21103 if($Name=~/((.+?)\.$Ext)\Z/)
21104 { # netapi32.dll
21105 if($Type eq "name")
21106 { # netapi32
21107 return $2;
21108 }
21109 elsif($Type eq "name+ext")
21110 { # netapi32.dll
21111 return $1;
21112 }
21113 elsif($Type eq "version")
21114 { # DLL version embedded
21115 # at binary-level
21116 return "";
21117 }
21118 elsif($Type eq "short")
21119 { # netapi32
21120 return $2;
21121 }
21122 elsif($Type eq "shortest")
21123 { # netapi
21124 return shortest_name($2);
21125 }
21126 }
21127 return "";# error
21128}
21129
21130sub shortest_name($)
21131{
21132 my $Name = $_[0];
21133 # remove prefix
21134 $Name=~s/\A(lib|open)//;
21135 # remove suffix
21136 $Name=~s/[\W\d_]+\Z//i;
21137 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21138 return $Name;
21139}
21140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021141sub createSymbolsList($$$$$)
21142{
21143 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21144 read_ABI_Dump(1, $DPath);
21145 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021146 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021147 }
21148 my %SymbolHeaderLib = ();
21149 my $Total = 0;
21150 # Get List
21151 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21152 {
21153 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021154 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021155 next;
21156 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021157 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021158 { # skip other symbols
21159 next;
21160 }
21161 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21162 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021163 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021164 next;
21165 }
21166 my $DyLib = $Symbol_Library{1}{$Symbol};
21167 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021168 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021169 next;
21170 }
21171 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21172 $Total+=1;
21173 }
21174 # Draw List
21175 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21176 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21177 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21178 {
21179 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21180 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021181 my %NS_Symbol = ();
21182 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021183 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021184 }
21185 foreach my $NameSpace (sort keys(%NS_Symbol))
21186 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021187 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021188 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21189 foreach my $Symbol (@SortedInterfaces)
21190 {
21191 my $SubReport = "";
21192 my $Signature = get_Signature($Symbol, 1);
21193 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021194 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021195 }
21196 if($Symbol=~/\A(_Z|\?)/)
21197 {
21198 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021199 $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 +040021200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021201 else {
21202 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21203 }
21204 }
21205 else
21206 {
21207 if($Signature) {
21208 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21209 }
21210 else {
21211 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21212 }
21213 }
21214 $SYMBOLS_LIST .= $SubReport;
21215 }
21216 }
21217 $SYMBOLS_LIST .= "<br/>\n";
21218 }
21219 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021220 # clear info
21221 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21222 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21223 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21224 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021225 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021226 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021227 my $CssStyles = readModule("Styles", "SymbolsList.css");
21228 my $JScripts = readModule("Scripts", "Sections.js");
21229 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021230 my $Title = "$LName: public symbols";
21231 my $Keywords = "$LName, API, symbols";
21232 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021233 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021234 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021235 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021236 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021237 writeFile($SaveTo, $SYMBOLS_LIST);
21238}
21239
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021240sub add_target_libs($)
21241{
21242 foreach (@{$_[0]}) {
21243 $TargetLibs{$_} = 1;
21244 }
21245}
21246
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021247sub is_target_lib($)
21248{
21249 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021250 if(not $LName) {
21251 return 0;
21252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021253 if($TargetLibraryName
21254 and $LName!~/\Q$TargetLibraryName\E/) {
21255 return 0;
21256 }
21257 if(keys(%TargetLibs)
21258 and not $TargetLibs{$LName}
21259 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21260 return 0;
21261 }
21262 return 1;
21263}
21264
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021265sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021266{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021267 my ($H, $V) = @_;
21268 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021269 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021270 if($TargetHeaders{$V}{$H}) {
21271 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021272 }
21273 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021274 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021275}
21276
21277sub checkVersionNum($$)
21278{
21279 my ($LibVersion, $Path) = @_;
21280 if(my $VerNum = $TargetVersion{$LibVersion}) {
21281 return $VerNum;
21282 }
21283 my $UsedAltDescr = 0;
21284 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021285 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021286 next if(isDump($Part)); # ABI dump
21287 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021288 my $VerNum = "";
21289 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021290 {
21291 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021292 $VerNum = parse_libname($Part, "version", $OStarget);
21293 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021294 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021295 }
21296 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021297 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21298 {
21299 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021300 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021301 }
21302 if($VerNum ne "")
21303 {
21304 $TargetVersion{$LibVersion} = $VerNum;
21305 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021306 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021307 }
21308 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021309 printMsg("WARNING", "setting ".($LibVersion==1?"1st":"2nd")." version number to \"$VerNum\" (use -v$LibVersion option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021310 }
21311 return $TargetVersion{$LibVersion};
21312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021313 }
21314 if($UsedAltDescr)
21315 {
21316 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021317 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021318 }
21319 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021320 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021321 }
21322 }
21323}
21324
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021325sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021326{
21327 my $Str = $_[0];
21328 return "" if(not $Str);
21329 $Str=~s/\Q$TargetLibraryName\E//g;
21330 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021331 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021332 return $2;
21333 }
21334 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21335 return $V;
21336 }
21337 return "";
21338}
21339
21340sub readLibs($)
21341{
21342 my $LibVersion = $_[0];
21343 if($OStarget eq "windows")
21344 { # dumpbin.exe will crash
21345 # without VS Environment
21346 check_win32_env();
21347 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021348 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021349 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021350 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021351}
21352
21353sub dump_sorting($)
21354{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021355 my $Hash = $_[0];
21356 return [] if(not $Hash);
21357 my @Keys = keys(%{$Hash});
21358 return [] if($#Keys<0);
21359 if($Keys[0]=~/\A\d+\Z/)
21360 { # numbers
21361 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021362 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021363 else
21364 { # strings
21365 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021366 }
21367}
21368
21369sub printMsg($$)
21370{
21371 my ($Type, $Msg) = @_;
21372 if($Type!~/\AINFO/) {
21373 $Msg = $Type.": ".$Msg;
21374 }
21375 if($Type!~/_C\Z/) {
21376 $Msg .= "\n";
21377 }
21378 if($Quiet)
21379 { # --quiet option
21380 appendFile($COMMON_LOG_PATH, $Msg);
21381 }
21382 else
21383 {
21384 if($Type eq "ERROR") {
21385 print STDERR $Msg;
21386 }
21387 else {
21388 print $Msg;
21389 }
21390 }
21391}
21392
21393sub exitStatus($$)
21394{
21395 my ($Code, $Msg) = @_;
21396 printMsg("ERROR", $Msg);
21397 exit($ERROR_CODE{$Code});
21398}
21399
21400sub exitReport()
21401{ # the tool has run without any errors
21402 printReport();
21403 if($COMPILE_ERRORS)
21404 { # errors in headers may add false positives/negatives
21405 exit($ERROR_CODE{"Compile_Error"});
21406 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021407 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21408 { # --binary
21409 exit($ERROR_CODE{"Incompatible"});
21410 }
21411 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21412 { # --source
21413 exit($ERROR_CODE{"Incompatible"});
21414 }
21415 elsif($RESULT{"Source"}{"Problems"}
21416 or $RESULT{"Binary"}{"Problems"})
21417 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021418 exit($ERROR_CODE{"Incompatible"});
21419 }
21420 else {
21421 exit($ERROR_CODE{"Compatible"});
21422 }
21423}
21424
21425sub readRules($)
21426{
21427 my $Kind = $_[0];
21428 if(not -f $RULES_PATH{$Kind}) {
21429 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21430 }
21431 my $Content = readFile($RULES_PATH{$Kind});
21432 while(my $Rule = parseTag(\$Content, "rule"))
21433 {
21434 my $RId = parseTag(\$Rule, "id");
21435 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21436 foreach my $Prop (@Properties) {
21437 if(my $Value = parseTag(\$Rule, lc($Prop)))
21438 {
21439 $Value=~s/\n[ ]*//;
21440 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21441 }
21442 }
21443 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21444 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21445 }
21446 else {
21447 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21448 }
21449 }
21450}
21451
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021452sub getReportPath($)
21453{
21454 my $Level = $_[0];
21455 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21456 if($Level eq "Binary")
21457 {
21458 if($BinaryReportPath)
21459 { # --bin-report-path
21460 return $BinaryReportPath;
21461 }
21462 elsif($OutputReportPath)
21463 { # --report-path
21464 return $OutputReportPath;
21465 }
21466 else
21467 { # default
21468 return $Dir."/abi_compat_report.$ReportFormat";
21469 }
21470 }
21471 elsif($Level eq "Source")
21472 {
21473 if($SourceReportPath)
21474 { # --src-report-path
21475 return $SourceReportPath;
21476 }
21477 elsif($OutputReportPath)
21478 { # --report-path
21479 return $OutputReportPath;
21480 }
21481 else
21482 { # default
21483 return $Dir."/src_compat_report.$ReportFormat";
21484 }
21485 }
21486 else
21487 {
21488 if($OutputReportPath)
21489 { # --report-path
21490 return $OutputReportPath;
21491 }
21492 else
21493 { # default
21494 return $Dir."/compat_report.$ReportFormat";
21495 }
21496 }
21497}
21498
21499sub printStatMsg($)
21500{
21501 my $Level = $_[0];
21502 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21503}
21504
21505sub listAffected($)
21506{
21507 my $Level = $_[0];
21508 my $List = "";
21509 foreach (keys(%{$TotalAffected{$Level}}))
21510 {
21511 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21512 { # skip "Low"-severity problems
21513 next;
21514 }
21515 $List .= "$_\n";
21516 }
21517 my $Dir = get_dirname(getReportPath($Level));
21518 if($Level eq "Binary") {
21519 writeFile($Dir."/abi_affected.txt", $List);
21520 }
21521 elsif($Level eq "Source") {
21522 writeFile($Dir."/src_affected.txt", $List);
21523 }
21524}
21525
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021526sub printReport()
21527{
21528 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021529 createReport();
21530 if($JoinReport or $DoubleReport)
21531 {
21532 if($RESULT{"Binary"}{"Problems"}
21533 or $RESULT{"Source"}{"Problems"}) {
21534 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021535 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021536 else {
21537 printMsg("INFO", "result: COMPATIBLE");
21538 }
21539 printStatMsg("Binary");
21540 printStatMsg("Source");
21541 if($ListAffected)
21542 { # --list-affected
21543 listAffected("Binary");
21544 listAffected("Source");
21545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021546 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021547 elsif($BinaryOnly)
21548 {
21549 if($RESULT{"Binary"}{"Problems"}) {
21550 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21551 }
21552 else {
21553 printMsg("INFO", "result: COMPATIBLE");
21554 }
21555 printStatMsg("Binary");
21556 if($ListAffected)
21557 { # --list-affected
21558 listAffected("Binary");
21559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021560 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021561 elsif($SourceOnly)
21562 {
21563 if($RESULT{"Source"}{"Problems"}) {
21564 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21565 }
21566 else {
21567 printMsg("INFO", "result: COMPATIBLE");
21568 }
21569 printStatMsg("Source");
21570 if($ListAffected)
21571 { # --list-affected
21572 listAffected("Source");
21573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021574 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021575 if($StdOut)
21576 {
21577 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021578 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021579 printMsg("INFO", "compatibility report has been generated to stdout");
21580 }
21581 else
21582 { # default
21583 printMsg("INFO", "compatibility reports have been generated to stdout");
21584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021585 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021586 else
21587 {
21588 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021589 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021590 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21591 }
21592 elsif($DoubleReport)
21593 { # default
21594 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21595 }
21596 elsif($BinaryOnly)
21597 { # --binary
21598 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21599 }
21600 elsif($SourceOnly)
21601 { # --source
21602 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021604 }
21605}
21606
21607sub check_win32_env()
21608{
21609 if(not $ENV{"DevEnvDir"}
21610 or not $ENV{"LIB"}) {
21611 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21612 }
21613}
21614
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021615sub diffSets($$)
21616{
21617 my ($S1, $S2) = @_;
21618 my @SK1 = keys(%{$S1});
21619 my @SK2 = keys(%{$S2});
21620 if($#SK1!=$#SK2) {
21621 return 1;
21622 }
21623 foreach my $K1 (@SK1)
21624 {
21625 if(not defined $S2->{$K1}) {
21626 return 1;
21627 }
21628 }
21629 return 0;
21630}
21631
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021632sub defaultDumpPath($$)
21633{
21634 my ($N, $V) = @_;
21635 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21636}
21637
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021638sub create_ABI_Dump()
21639{
21640 if(not -e $DumpAPI) {
21641 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21642 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021643
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021644 my @DParts = split(/\s*,\s*/, $DumpAPI);
21645 foreach my $Part (@DParts)
21646 {
21647 if(not -e $Part) {
21648 exitStatus("Access_Error", "can't access \'$Part\'");
21649 }
21650 }
21651 checkVersionNum(1, $DumpAPI);
21652 foreach my $Part (@DParts)
21653 {
21654 if(isDump($Part)) {
21655 read_ABI_Dump(1, $Part);
21656 }
21657 else {
21658 readDescriptor(1, createDescriptor(1, $Part));
21659 }
21660 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021661
21662 if(not $Descriptor{1}{"Version"})
21663 { # set to default: X
21664 $Descriptor{1}{"Version"} = "X";
21665 }
21666
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021667 initLogging(1);
21668 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021669
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021670 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021671 if($OutputDumpPath)
21672 { # user defined path
21673 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021674 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021675 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21676
21677 if(not $Archive and not $StdOut)
21678 { # check archive utilities
21679 if($OSgroup eq "windows")
21680 { # using zip
21681 my $ZipCmd = get_CmdPath("zip");
21682 if(not $ZipCmd) {
21683 exitStatus("Not_Found", "can't find \"zip\"");
21684 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021685 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021686 else
21687 { # using tar and gzip
21688 my $TarCmd = get_CmdPath("tar");
21689 if(not $TarCmd) {
21690 exitStatus("Not_Found", "can't find \"tar\"");
21691 }
21692 my $GzipCmd = get_CmdPath("gzip");
21693 if(not $GzipCmd) {
21694 exitStatus("Not_Found", "can't find \"gzip\"");
21695 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021696 }
21697 }
21698
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021699 if(not $Descriptor{1}{"Dump"})
21700 {
21701 if(not $CheckHeadersOnly) {
21702 readLibs(1);
21703 }
21704 if($CheckHeadersOnly) {
21705 setLanguage(1, "C++");
21706 }
21707 if(not $CheckObjectsOnly) {
21708 searchForHeaders(1);
21709 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021710 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021711 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021712 if(not $Descriptor{1}{"Dump"})
21713 {
21714 if($Descriptor{1}{"Headers"}) {
21715 readHeaders(1);
21716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021717 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021718 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021719 if(not keys(%{$SymbolInfo{1}}))
21720 { # check if created dump is valid
21721 if(not $ExtendedCheck and not $CheckObjectsOnly)
21722 {
21723 if($CheckHeadersOnly) {
21724 exitStatus("Empty_Set", "the set of public symbols is empty");
21725 }
21726 else {
21727 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21728 }
21729 }
21730 }
21731 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021732 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021733 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21734 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021735 if($ExtraDump)
21736 { # add unmangled names to the ABI dump
21737 my @Names = ();
21738 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21739 {
21740 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21741 push(@Names, $MnglName);
21742 }
21743 }
21744 translateSymbols(@Names, 1);
21745 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21746 {
21747 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21748 {
21749 if(my $Unmangled = $tr_name{$MnglName})
21750 {
21751 if($MnglName ne $Unmangled) {
21752 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21753 }
21754 }
21755 }
21756 }
21757 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021758
21759 my %GccConstants = (); # built-in GCC constants
21760 foreach my $Name (keys(%{$Constants{1}}))
21761 {
21762 if(not defined $Constants{1}{$Name}{"Header"})
21763 {
21764 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21765 delete($Constants{1}{$Name});
21766 }
21767 }
21768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021769 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021770 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021771 "TypeInfo" => $TypeInfo{1},
21772 "SymbolInfo" => $SymbolInfo{1},
21773 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021774 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021775 "SymbolVersion" => $SymVer{1},
21776 "LibraryVersion" => $Descriptor{1}{"Version"},
21777 "LibraryName" => $TargetLibraryName,
21778 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021779 "SkipTypes" => $SkipTypes{1},
21780 "SkipSymbols" => $SkipSymbols{1},
21781 "SkipNameSpaces" => $SkipNameSpaces{1},
21782 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021783 "Headers" => \%HeadersInfo,
21784 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021785 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021786 "NameSpaces" => $NestedNameSpaces{1},
21787 "Target" => $OStarget,
21788 "Arch" => getArch(1),
21789 "WordSize" => $WORD_SIZE{1},
21790 "GccVersion" => get_dumpversion($GCC_PATH),
21791 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21792 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21793 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021794 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021795 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021796 }
21797 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021798 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021800 if($ExtendedCheck)
21801 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021802 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021803 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021804 if($BinaryOnly)
21805 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021806 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021807 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021808 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021809 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021810 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021811 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21812 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021813 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021814
21815 my $ABI_DUMP = "";
21816 if($UseXML)
21817 {
21818 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021819 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021820 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021821 else
21822 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021823 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021825 if($StdOut)
21826 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021827 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021828 printMsg("INFO", "ABI dump has been generated to stdout");
21829 return;
21830 }
21831 else
21832 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021833 my ($DDir, $DName) = separate_path($DumpPath);
21834 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021835 if(not $Archive) {
21836 $DPath = $DumpPath;
21837 }
21838
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021839 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021840
21841 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021842 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021843 close(DUMP);
21844
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021845 if(not -s $DPath) {
21846 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21847 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021848 if($Archive) {
21849 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021850 }
21851
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021852 if($OutputDumpPath) {
21853 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021854 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021855 else {
21856 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21857 }
21858 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 +040021859 }
21860}
21861
21862sub quickEmptyReports()
21863{ # Quick "empty" reports
21864 # 4 times faster than merging equal dumps
21865 # NOTE: the dump contains the "LibraryVersion" attribute
21866 # if you change the version, then your dump will be different
21867 # OVERCOME: use -v1 and v2 options for comparing dumps
21868 # and don't change version in the XML descriptor (and dumps)
21869 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21870 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21871 {
21872 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21873 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21874 if($FilePath1 and $FilePath2)
21875 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021876 my $Line = readLineNum($FilePath1, 0);
21877 if($Line=~/xml/)
21878 { # XML format
21879 # is not supported yet
21880 return;
21881 }
21882
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021883 local $/ = undef;
21884
21885 open(DUMP1, $FilePath1);
21886 my $Content1 = <DUMP1>;
21887 close(DUMP1);
21888
21889 open(DUMP2, $FilePath2);
21890 my $Content2 = <DUMP2>;
21891 close(DUMP2);
21892
21893 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021894 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021895 # clean memory
21896 undef $Content2;
21897
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021898 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021899 my $ABIdump = eval($Content1);
21900
21901 # clean memory
21902 undef $Content1;
21903
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021904 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021905 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 +040021906 }
21907 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021908 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021909 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21910 }
21911 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021912 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021913 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21914 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021915 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021916 read_Libs_DumpInfo($ABIdump, 1);
21917 read_Machine_DumpInfo($ABIdump, 1);
21918 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021919
21920 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21921 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21922
21923 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21924 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21925
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021926 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21927 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21928 exitReport();
21929 }
21930 }
21931 }
21932}
21933
21934sub initLogging($)
21935{
21936 my $LibVersion = $_[0];
21937 # create log directory
21938 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21939 if($OutputLogPath{$LibVersion})
21940 { # user-defined by -log-path option
21941 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21942 }
21943 if($LogMode ne "n") {
21944 mkpath($LOG_DIR);
21945 }
21946 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021947 if($Debug)
21948 { # debug directory
21949 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021950
21951 if(not $ExtraInfo)
21952 { # enable --extra-info
21953 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021955 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021956 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021957}
21958
21959sub writeLog($$)
21960{
21961 my ($LibVersion, $Msg) = @_;
21962 if($LogMode ne "n") {
21963 appendFile($LOG_PATH{$LibVersion}, $Msg);
21964 }
21965}
21966
21967sub resetLogging($)
21968{
21969 my $LibVersion = $_[0];
21970 if($LogMode!~/a|n/)
21971 { # remove old log
21972 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021973 if($Debug) {
21974 rmtree($DEBUG_PATH{$LibVersion});
21975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021976 }
21977}
21978
21979sub printErrorLog($)
21980{
21981 my $LibVersion = $_[0];
21982 if($LogMode ne "n") {
21983 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21984 }
21985}
21986
21987sub isDump($)
21988{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021989 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21990 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021991 return $1;
21992 }
21993 return 0;
21994}
21995
21996sub isDump_U($)
21997{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021998 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021999 return $1;
22000 }
22001 return 0;
22002}
22003
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022004sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022005{
22006 # read input XML descriptors or ABI dumps
22007 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022008 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022009 }
22010 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
22011 foreach my $Part (@DParts1)
22012 {
22013 if(not -e $Part) {
22014 exitStatus("Access_Error", "can't access \'$Part\'");
22015 }
22016 }
22017 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022018 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022019 }
22020 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22021 foreach my $Part (@DParts2)
22022 {
22023 if(not -e $Part) {
22024 exitStatus("Access_Error", "can't access \'$Part\'");
22025 }
22026 }
22027 detect_default_paths("bin"); # to extract dumps
22028 if($#DParts1==0 and $#DParts2==0
22029 and isDump($Descriptor{1}{"Path"})
22030 and isDump($Descriptor{2}{"Path"}))
22031 { # optimization: equal ABI dumps
22032 quickEmptyReports();
22033 }
22034 checkVersionNum(1, $Descriptor{1}{"Path"});
22035 checkVersionNum(2, $Descriptor{2}{"Path"});
22036 printMsg("INFO", "preparation, please wait ...");
22037 foreach my $Part (@DParts1)
22038 {
22039 if(isDump($Part)) {
22040 read_ABI_Dump(1, $Part);
22041 }
22042 else {
22043 readDescriptor(1, createDescriptor(1, $Part));
22044 }
22045 }
22046 foreach my $Part (@DParts2)
22047 {
22048 if(isDump($Part)) {
22049 read_ABI_Dump(2, $Part);
22050 }
22051 else {
22052 readDescriptor(2, createDescriptor(2, $Part));
22053 }
22054 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022055
22056 if(not $Descriptor{1}{"Version"})
22057 { # set to default: X
22058 $Descriptor{1}{"Version"} = "X";
22059 }
22060
22061 if(not $Descriptor{2}{"Version"})
22062 { # set to default: Y
22063 $Descriptor{2}{"Version"} = "Y";
22064 }
22065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022066 initLogging(1);
22067 initLogging(2);
22068 # check consistency
22069 if(not $Descriptor{1}{"Headers"}
22070 and not $Descriptor{1}{"Libs"}) {
22071 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22072 }
22073 if(not $Descriptor{2}{"Headers"}
22074 and not $Descriptor{2}{"Libs"}) {
22075 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22076 }
22077 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22078 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22079 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22080 }
22081 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22082 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22083 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22084 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022085 if(not $Descriptor{1}{"Headers"})
22086 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022087 if($CheckHeadersOnly_Opt) {
22088 exitStatus("Error", "can't find header files info in descriptor d1");
22089 }
22090 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022091 if(not $Descriptor{2}{"Headers"})
22092 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022093 if($CheckHeadersOnly_Opt) {
22094 exitStatus("Error", "can't find header files info in descriptor d2");
22095 }
22096 }
22097 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022098 or not $Descriptor{2}{"Headers"})
22099 {
22100 if(not $CheckObjectsOnly_Opt)
22101 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022102 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22103 $CheckObjectsOnly = 1;
22104 }
22105 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022106 if(not $Descriptor{1}{"Libs"})
22107 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022108 if($CheckObjectsOnly_Opt) {
22109 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22110 }
22111 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022112 if(not $Descriptor{2}{"Libs"})
22113 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022114 if($CheckObjectsOnly_Opt) {
22115 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22116 }
22117 }
22118 if(not $Descriptor{1}{"Libs"}
22119 or not $Descriptor{2}{"Libs"})
22120 { # comparing standalone header files
22121 # comparing ABI dumps created with --headers-only
22122 if(not $CheckHeadersOnly_Opt)
22123 {
22124 printMsg("WARNING", "checking headers only");
22125 $CheckHeadersOnly = 1;
22126 }
22127 }
22128 if($UseDumps)
22129 { # --use-dumps
22130 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022131 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22132 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022133
22134 unlink($DumpPath1);
22135 unlink($DumpPath2);
22136
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022137 my $pid = fork();
22138 if($pid)
22139 { # dump on two CPU cores
22140 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22141 if($RelativeDirectory{1}) {
22142 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22143 }
22144 if($OutputLogPath{1}) {
22145 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22146 }
22147 if($CrossGcc) {
22148 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22149 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022150 if($Quiet)
22151 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022152 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022153 @PARAMS = (@PARAMS, "-logging-mode", "a");
22154 }
22155 elsif($LogMode and $LogMode ne "w")
22156 { # "w" is default
22157 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022158 }
22159 if($ExtendedCheck) {
22160 @PARAMS = (@PARAMS, "-extended");
22161 }
22162 if($UserLang) {
22163 @PARAMS = (@PARAMS, "-lang", $UserLang);
22164 }
22165 if($TargetVersion{1}) {
22166 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22167 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022168 if($BinaryOnly) {
22169 @PARAMS = (@PARAMS, "-binary");
22170 }
22171 if($SourceOnly) {
22172 @PARAMS = (@PARAMS, "-source");
22173 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022174 if($SortDump) {
22175 @PARAMS = (@PARAMS, "-sort");
22176 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022177 if($DumpFormat and $DumpFormat ne "perl") {
22178 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22179 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022180 if($CheckHeadersOnly) {
22181 @PARAMS = (@PARAMS, "-headers-only");
22182 }
22183 if($CheckObjectsOnly) {
22184 @PARAMS = (@PARAMS, "-objects-only");
22185 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022186 if($Debug)
22187 {
22188 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022189 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022191 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022192 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022193 exit(1);
22194 }
22195 }
22196 else
22197 { # child
22198 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22199 if($RelativeDirectory{2}) {
22200 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22201 }
22202 if($OutputLogPath{2}) {
22203 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22204 }
22205 if($CrossGcc) {
22206 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22207 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022208 if($Quiet)
22209 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022210 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022211 @PARAMS = (@PARAMS, "-logging-mode", "a");
22212 }
22213 elsif($LogMode and $LogMode ne "w")
22214 { # "w" is default
22215 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022216 }
22217 if($ExtendedCheck) {
22218 @PARAMS = (@PARAMS, "-extended");
22219 }
22220 if($UserLang) {
22221 @PARAMS = (@PARAMS, "-lang", $UserLang);
22222 }
22223 if($TargetVersion{2}) {
22224 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22225 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022226 if($BinaryOnly) {
22227 @PARAMS = (@PARAMS, "-binary");
22228 }
22229 if($SourceOnly) {
22230 @PARAMS = (@PARAMS, "-source");
22231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022232 if($SortDump) {
22233 @PARAMS = (@PARAMS, "-sort");
22234 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022235 if($DumpFormat and $DumpFormat ne "perl") {
22236 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22237 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022238 if($CheckHeadersOnly) {
22239 @PARAMS = (@PARAMS, "-headers-only");
22240 }
22241 if($CheckObjectsOnly) {
22242 @PARAMS = (@PARAMS, "-objects-only");
22243 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022244 if($Debug)
22245 {
22246 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022247 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022249 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022250 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022251 exit(1);
22252 }
22253 else {
22254 exit(0);
22255 }
22256 }
22257 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022258
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022259 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022260 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22261 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022262 if($TargetTitle ne $TargetLibraryName) {
22263 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022264 }
22265 if($ShowRetVal) {
22266 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22267 }
22268 if($CrossGcc) {
22269 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22270 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022271 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22272 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022273 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022274 }
22275 if($ReportFormat and $ReportFormat ne "html")
22276 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022277 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022279 if($OutputReportPath) {
22280 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22281 }
22282 if($BinaryReportPath) {
22283 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22284 }
22285 if($SourceReportPath) {
22286 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22287 }
22288 if($LoggingPath) {
22289 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22290 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022291 if($CheckHeadersOnly) {
22292 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22293 }
22294 if($CheckObjectsOnly) {
22295 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22296 }
22297 if($BinaryOnly) {
22298 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22299 }
22300 if($SourceOnly) {
22301 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22302 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022303 if($Debug)
22304 {
22305 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22306 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022308 system("perl", $0, @CMP_PARAMS);
22309 exit($?>>8);
22310 }
22311 if(not $Descriptor{1}{"Dump"}
22312 or not $Descriptor{2}{"Dump"})
22313 { # need GCC toolchain to analyze
22314 # header files and libraries
22315 detect_default_paths("inc|lib|gcc");
22316 }
22317 if(not $Descriptor{1}{"Dump"})
22318 {
22319 if(not $CheckHeadersOnly) {
22320 readLibs(1);
22321 }
22322 if($CheckHeadersOnly) {
22323 setLanguage(1, "C++");
22324 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022325 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022326 searchForHeaders(1);
22327 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022328 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022329 }
22330 if(not $Descriptor{2}{"Dump"})
22331 {
22332 if(not $CheckHeadersOnly) {
22333 readLibs(2);
22334 }
22335 if($CheckHeadersOnly) {
22336 setLanguage(2, "C++");
22337 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022338 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022339 searchForHeaders(2);
22340 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022341 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022342 }
22343 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22344 { # support for old ABI dumps
22345 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022346 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022347 {
22348 $WORD_SIZE{1} = $WORD_SIZE{2};
22349 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22350 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022351 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022352 {
22353 $WORD_SIZE{2} = $WORD_SIZE{1};
22354 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22355 }
22356 }
22357 elsif(not $WORD_SIZE{1}
22358 and not $WORD_SIZE{2})
22359 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022360 $WORD_SIZE{1} = "4";
22361 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022362 }
22363 if($Descriptor{1}{"Dump"})
22364 { # support for old ABI dumps
22365 prepareTypes(1);
22366 }
22367 if($Descriptor{2}{"Dump"})
22368 { # support for old ABI dumps
22369 prepareTypes(2);
22370 }
22371 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22372 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22373 }
22374 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022375 if(not $CheckObjectsOnly)
22376 {
22377 if($Descriptor{1}{"Headers"}
22378 and not $Descriptor{1}{"Dump"}) {
22379 readHeaders(1);
22380 }
22381 if($Descriptor{2}{"Headers"}
22382 and not $Descriptor{2}{"Dump"}) {
22383 readHeaders(2);
22384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022385 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022386
22387 # clean memory
22388 %SystemHeaders = ();
22389 %mangled_name_gcc = ();
22390
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022391 prepareSymbols(1);
22392 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022393
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022394 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022395 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022396
22397 # Virtual Tables
22398 registerVTable(1);
22399 registerVTable(2);
22400
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022401 if(not checkDump(1, "1.22")
22402 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022403 { # support for old ABI dumps
22404 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22405 {
22406 if($ClassName=~/</)
22407 { # templates
22408 if(not defined $VirtualTable{1}{$ClassName})
22409 { # synchronize
22410 delete($VirtualTable{2}{$ClassName});
22411 }
22412 }
22413 }
22414 }
22415
22416 registerOverriding(1);
22417 registerOverriding(2);
22418
22419 setVirtFuncPositions(1);
22420 setVirtFuncPositions(2);
22421
22422 # Other
22423 addParamNames(1);
22424 addParamNames(2);
22425
22426 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022427}
22428
22429sub compareAPIs($)
22430{
22431 my $Level = $_[0];
22432 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022433 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022434 if($Level eq "Binary") {
22435 printMsg("INFO", "comparing ABIs ...");
22436 }
22437 else {
22438 printMsg("INFO", "comparing APIs ...");
22439 }
22440 if($CheckHeadersOnly
22441 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022443 detectAdded_H($Level);
22444 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022445 }
22446 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022447 { # added/removed in libs
22448 detectAdded($Level);
22449 detectRemoved($Level);
22450 }
22451 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022452 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022453 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022454 if(keys(%{$CheckedSymbols{$Level}})) {
22455 mergeConstants($Level);
22456 }
22457 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022458
22459 $Cache{"mergeTypes"} = (); # free memory
22460
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022461 if($CheckHeadersOnly
22462 or $Level eq "Source")
22463 { # added/removed in headers
22464 mergeHeaders($Level);
22465 }
22466 else
22467 { # added/removed in libs
22468 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022469 }
22470}
22471
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022472sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022473{
22474 my %Opts = (
22475 "OStarget"=>$OStarget,
22476 "Debug"=>$Debug,
22477 "Quiet"=>$Quiet,
22478 "LogMode"=>$LogMode,
22479 "CheckHeadersOnly"=>$CheckHeadersOnly,
22480
22481 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022482 "GCC_PATH"=>$GCC_PATH,
22483 "TargetSysInfo"=>$TargetSysInfo,
22484 "CrossPrefix"=>$CrossPrefix,
22485 "TargetLibraryName"=>$TargetLibraryName,
22486 "CrossGcc"=>$CrossGcc,
22487 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022488 "NoStdInc"=>$NoStdInc,
22489
22490 "BinaryOnly" => $BinaryOnly,
22491 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022492 );
22493 return \%Opts;
22494}
22495
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022496sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022497{
22498 my %CODE_ERROR = reverse(%ERROR_CODE);
22499 return $CODE_ERROR{$_[0]};
22500}
22501
22502sub scenario()
22503{
22504 if($StdOut)
22505 { # enable quiet mode
22506 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022507 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022508 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022509 if(not $LogMode)
22510 { # default
22511 $LogMode = "w";
22512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022513 if($UserLang)
22514 { # --lang=C++
22515 $UserLang = uc($UserLang);
22516 $COMMON_LANGUAGE{1}=$UserLang;
22517 $COMMON_LANGUAGE{2}=$UserLang;
22518 }
22519 if($LoggingPath)
22520 {
22521 $OutputLogPath{1} = $LoggingPath;
22522 $OutputLogPath{2} = $LoggingPath;
22523 if($Quiet) {
22524 $COMMON_LOG_PATH = $LoggingPath;
22525 }
22526 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022527 if($Quick) {
22528 $ADD_TMPL_INSTANCES = 0;
22529 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022530 if($OutputDumpPath)
22531 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022532 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022533 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22534 }
22535 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022536 if($BinaryOnly and $SourceOnly)
22537 { # both --binary and --source
22538 # is the default mode
22539 $DoubleReport = 1;
22540 $JoinReport = 0;
22541 $BinaryOnly = 0;
22542 $SourceOnly = 0;
22543 if($OutputReportPath)
22544 { # --report-path
22545 $DoubleReport = 0;
22546 $JoinReport = 1;
22547 }
22548 }
22549 elsif($BinaryOnly or $SourceOnly)
22550 { # --binary or --source
22551 $DoubleReport = 0;
22552 $JoinReport = 0;
22553 }
22554 if($UseXML)
22555 { # --xml option
22556 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022557 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 if($ReportFormat)
22560 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022561 $ReportFormat = lc($ReportFormat);
22562 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022563 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022564 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022565 if($ReportFormat eq "htm")
22566 { # HTM == HTML
22567 $ReportFormat = "html";
22568 }
22569 elsif($ReportFormat eq "xml")
22570 { # --report-format=XML equal to --xml
22571 $UseXML = 1;
22572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022573 }
22574 else
22575 { # default: HTML
22576 $ReportFormat = "html";
22577 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022578 if($DumpFormat)
22579 { # validate
22580 $DumpFormat = lc($DumpFormat);
22581 if($DumpFormat!~/\A(xml|perl)\Z/) {
22582 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22583 }
22584 if($DumpFormat eq "xml")
22585 { # --dump-format=XML equal to --xml
22586 $UseXML = 1;
22587 }
22588 }
22589 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022590 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022591 $DumpFormat = "perl";
22592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022593 if($Quiet and $LogMode!~/a|n/)
22594 { # --quiet log
22595 if(-f $COMMON_LOG_PATH) {
22596 unlink($COMMON_LOG_PATH);
22597 }
22598 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022599 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022600 $CheckUndefined = 1;
22601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022602 if($TestTool and $UseDumps)
22603 { # --test && --use-dumps == --test-dump
22604 $TestDump = 1;
22605 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022606 if($Tolerant)
22607 { # enable all
22608 $Tolerance = 1234;
22609 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022610 if($Help)
22611 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022612 HELP_MESSAGE();
22613 exit(0);
22614 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022615 if($InfoMsg)
22616 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022617 INFO_MESSAGE();
22618 exit(0);
22619 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022620 if($ShowVersion)
22621 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022622 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 +040022623 exit(0);
22624 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022625 if($DumpVersion)
22626 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022627 printMsg("INFO", $TOOL_VERSION);
22628 exit(0);
22629 }
22630 if($ExtendedCheck) {
22631 $CheckHeadersOnly = 1;
22632 }
22633 if($SystemRoot_Opt)
22634 { # user defined root
22635 if(not -e $SystemRoot_Opt) {
22636 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22637 }
22638 $SystemRoot = $SystemRoot_Opt;
22639 $SystemRoot=~s/[\/]+\Z//g;
22640 if($SystemRoot) {
22641 $SystemRoot = get_abs_path($SystemRoot);
22642 }
22643 }
22644 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022645
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022646 if($SortDump)
22647 {
22648 $Data::Dumper::Useperl = 1;
22649 $Data::Dumper::Sortkeys = \&dump_sorting;
22650 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022651
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022652 if($TargetLibsPath)
22653 {
22654 if(not -f $TargetLibsPath) {
22655 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22656 }
22657 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22658 $TargetLibs{$Lib} = 1;
22659 }
22660 }
22661 if($TargetHeadersPath)
22662 { # --headers-list
22663 if(not -f $TargetHeadersPath) {
22664 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22665 }
22666 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22667 {
22668 $TargetHeaders{1}{$Header} = 1;
22669 $TargetHeaders{2}{$Header} = 1;
22670 }
22671 }
22672 if($TargetHeader)
22673 { # --header
22674 $TargetHeaders{1}{$TargetHeader} = 1;
22675 $TargetHeaders{2}{$TargetHeader} = 1;
22676 }
22677 if($TestTool
22678 or $TestDump)
22679 { # --test, --test-dump
22680 detect_default_paths("bin|gcc"); # to compile libs
22681 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022682 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022683 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022684 exit(0);
22685 }
22686 if($DumpSystem)
22687 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022688
22689 if(not $TargetSysInfo) {
22690 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22691 }
22692
22693 if(not -d $TargetSysInfo) {
22694 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22695 }
22696
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022697 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022698 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022699 { # system XML descriptor
22700 if(not -f $DumpSystem) {
22701 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22702 }
22703 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022704 foreach (@{$Ret->{"Tools"}})
22705 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022706 push_U($SystemPaths{"bin"}, $_);
22707 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022708 }
22709 if($Ret->{"CrossPrefix"}) {
22710 $CrossPrefix = $Ret->{"CrossPrefix"};
22711 }
22712 }
22713 elsif($SystemRoot_Opt)
22714 { # -sysroot "/" option
22715 # default target: /usr/lib, /usr/include
22716 # search libs: /usr/lib and /lib
22717 if(not -e $SystemRoot."/usr/lib") {
22718 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22719 }
22720 if(not -e $SystemRoot."/lib") {
22721 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22722 }
22723 if(not -e $SystemRoot."/usr/include") {
22724 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22725 }
22726 readSystemDescriptor("
22727 <name>
22728 $DumpSystem
22729 </name>
22730 <headers>
22731 $SystemRoot/usr/include
22732 </headers>
22733 <libs>
22734 $SystemRoot/usr/lib
22735 </libs>
22736 <search_libs>
22737 $SystemRoot/lib
22738 </search_libs>");
22739 }
22740 else {
22741 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22742 }
22743 detect_default_paths("bin|gcc"); # to check symbols
22744 if($OStarget eq "windows")
22745 { # to run dumpbin.exe
22746 # and undname.exe
22747 check_win32_env();
22748 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022749 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022750 exit(0);
22751 }
22752 if($CmpSystems)
22753 { # --cmp-systems
22754 detect_default_paths("bin"); # to extract dumps
22755 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022756 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022757 exit(0);
22758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022759 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022760 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022761 }
22762 else
22763 { # validate library name
22764 if($TargetLibraryName=~/[\*\/\\]/) {
22765 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22766 }
22767 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022768 if(not $TargetTitle) {
22769 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022770 }
22771 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22772 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22773 }
22774 if($SymbolsListPath)
22775 {
22776 if(not -f $SymbolsListPath) {
22777 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22778 }
22779 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22780 $SymbolsList{$Interface} = 1;
22781 }
22782 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022783 if($TypesListPath)
22784 {
22785 if(not -f $TypesListPath) {
22786 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22787 }
22788 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22789 $TypesList{$Type} = 1;
22790 }
22791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022792 if($SkipSymbolsListPath)
22793 {
22794 if(not -f $SkipSymbolsListPath) {
22795 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22796 }
22797 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022798 $SkipSymbols{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022799 }
22800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022801 if($SkipHeadersPath)
22802 {
22803 if(not -f $SkipHeadersPath) {
22804 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22805 }
22806 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022807 { # register for both versions
22808 $SkipHeadersList{1}{$Path} = 1;
22809 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022810 my ($CPath, $Type) = classifyPath($Path);
22811 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022812 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022813 }
22814 }
22815 if($ParamNamesPath)
22816 {
22817 if(not -f $ParamNamesPath) {
22818 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22819 }
22820 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22821 {
22822 if($Line=~s/\A(\w+)\;//)
22823 {
22824 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022825 if($Line=~/;(\d+);/)
22826 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022827 while($Line=~s/(\d+);(\w+)//) {
22828 $AddIntParams{$Interface}{$1}=$2;
22829 }
22830 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022831 else
22832 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022833 my $Num = 0;
22834 foreach my $Name (split(/;/, $Line)) {
22835 $AddIntParams{$Interface}{$Num++}=$Name;
22836 }
22837 }
22838 }
22839 }
22840 }
22841 if($AppPath)
22842 {
22843 if(not -f $AppPath) {
22844 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22845 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022846 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022847 $SymbolsList_App{$Interface} = 1;
22848 }
22849 }
22850 if($DumpAPI)
22851 { # --dump-abi
22852 # make an API dump
22853 create_ABI_Dump();
22854 exit($COMPILE_ERRORS);
22855 }
22856 # default: compare APIs
22857 # -d1 <path>
22858 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022859 compareInit();
22860 if($JoinReport or $DoubleReport)
22861 {
22862 compareAPIs("Binary");
22863 compareAPIs("Source");
22864 }
22865 elsif($BinaryOnly) {
22866 compareAPIs("Binary");
22867 }
22868 elsif($SourceOnly) {
22869 compareAPIs("Source");
22870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022871 exitReport();
22872}
22873
22874scenario();