blob: ffa3f45770f658e963c99a53bd88a0bf359e23c2 [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
9# 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
84my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate,
85$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
86$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030087%RelativeDirectory, $TargetLibraryFName, $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
150my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400151 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400152 "Dev"=>"https://github.com/lvc/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153);
154
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400155my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400156A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300157Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400158License: GNU LGPL or GNU GPL
159
160Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400161Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400162
163OLD.xml and NEW.xml are XML-descriptors:
164
165 <version>
166 1.0
167 </version>
168
169 <headers>
170 /path/to/headers/
171 </headers>
172
173 <libs>
174 /path/to/libraries/
175 </libs>
176
177More info: $CmdName --help\n";
178
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400179if($#ARGV==-1)
180{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400181 printMsg("INFO", $ShortUsage);
182 exit(0);
183}
184
185foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400186{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400187 if($ARGV[$_-1] eq ",")
188 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400189 $ARGV[$_-2].=",".$ARGV[$_];
190 splice(@ARGV, $_-1, 2);
191 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400192 elsif($ARGV[$_-1]=~/,\Z/)
193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 $ARGV[$_-1].=$ARGV[$_];
195 splice(@ARGV, $_, 1);
196 }
197 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400198 and $ARGV[$_] ne ",")
199 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400200 $ARGV[$_-1].=$ARGV[$_];
201 splice(@ARGV, $_, 1);
202 }
203}
204
205GetOptions("h|help!" => \$Help,
206 "i|info!" => \$InfoMsg,
207 "v|version!" => \$ShowVersion,
208 "dumpversion!" => \$DumpVersion,
209# general options
210 "l|lib|library=s" => \$TargetLibraryName,
211 "d1|old|o=s" => \$Descriptor{1}{"Path"},
212 "d2|new|n=s" => \$Descriptor{2}{"Path"},
213 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
214 "old-dumps!" => \$UseOldDumps,
215# extra options
216 "d|descriptor-template!" => \$GenerateTemplate,
217 "app|application=s" => \$AppPath,
218 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400219 "gcc-path|cross-gcc=s" => \$CrossGcc,
220 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
221 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400222 "sysroot=s" => \$SystemRoot_Opt,
223 "v1|version1|vnum=s" => \$TargetVersion{1},
224 "v2|version2=s" => \$TargetVersion{2},
225 "s|strict!" => \$StrictCompat,
226 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300227 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400228 "skip-symbols=s" => \$SkipSymbolsListPath,
229 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400231 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400232 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
233 "objects-only!" => \$CheckObjectsOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400234 "show-retval!" => \$ShowRetVal,
235 "use-dumps!" => \$UseDumps,
236 "nostdinc!" => \$NoStdInc,
237 "dump-system=s" => \$DumpSystem,
238 "sysinfo=s" => \$TargetSysInfo,
239 "cmp-systems!" => \$CmpSystems,
240 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400241 "ext|extended!" => \$ExtendedCheck,
242 "q|quiet!" => \$Quiet,
243 "stdout!" => \$StdOut,
244 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400245 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400246 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400248 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400249 "binary|bin|abi!" => \$BinaryOnly,
250 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400251 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400252# other options
253 "test!" => \$TestTool,
254 "test-dump!" => \$TestDump,
255 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400256 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400257 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400258 "p|params=s" => \$ParamNamesPath,
259 "relpath1|relpath=s" => \$RelativeDirectory{1},
260 "relpath2=s" => \$RelativeDirectory{2},
261 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400262 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400263 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400264 "bin-report-path=s" => \$BinaryReportPath,
265 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400266 "log-path=s" => \$LoggingPath,
267 "log1-path=s" => \$OutputLogPath{1},
268 "log2-path=s" => \$OutputLogPath{2},
269 "logging-mode=s" => \$LogMode,
270 "list-affected!" => \$ListAffected,
271 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400272 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400273 "extra-info=s" => \$ExtraInfo,
274 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400275 "force!" => \$Force,
276 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400277 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400278 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400279 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400280 "all-affected!" => \$AllAffected,
281 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400282) or ERR_MESSAGE();
283
284sub ERR_MESSAGE()
285{
286 printMsg("INFO", "\n".$ShortUsage);
287 exit($ERROR_CODE{"Error"});
288}
289
290my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
291my $SLIB_TYPE = $LIB_TYPE;
292if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
293{ # show as "shared" library
294 $SLIB_TYPE = "shared";
295}
296my $LIB_EXT = getLIB_EXT($OSgroup);
297my $AR_EXT = getAR_EXT($OSgroup);
298my $BYTE_SIZE = 8;
299my $COMMON_LOG_PATH = "logs/run.log";
300
301my $HelpMessage="
302NAME:
303 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400304 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400305
306DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400307 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400308 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
309 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
310 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
311 and/or source-level compatibility: changes in calling stack, v-table changes,
312 removed symbols, renamed fields, etc. Binary incompatibility may result in
313 crashing or incorrect behavior of applications built with an old version of
314 a library if they run on a new one. Source incompatibility may result in
315 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400316
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400317 The tool is intended for developers of software libraries and maintainers
318 of operating systems who are interested in ensuring backward compatibility,
319 i.e. allow old applications to run or to be recompiled with newer library
320 versions.
321
322 Also the tool can be used by ISVs for checking applications portability to
323 new library versions. Found issues can be taken into account when adapting
324 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400325
326 This tool is free software: you can redistribute it and/or modify it
327 under the terms of the GNU LGPL or GNU GPL.
328
329USAGE:
330 $CmdName [options]
331
332EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400333 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400334
335 OLD.xml and NEW.xml are XML-descriptors:
336
337 <version>
338 1.0
339 </version>
340
341 <headers>
342 /path1/to/header(s)/
343 /path2/to/header(s)/
344 ...
345 </headers>
346
347 <libs>
348 /path1/to/library(ies)/
349 /path2/to/library(ies)/
350 ...
351 </libs>
352
353INFORMATION OPTIONS:
354 -h|-help
355 Print this help.
356
357 -i|-info
358 Print complete info.
359
360 -v|-version
361 Print version information.
362
363 -dumpversion
364 Print the tool version ($TOOL_VERSION) and don't do anything else.
365
366GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400367 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400368 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400369
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400370 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371 Descriptor of 1st (old) library version.
372 It may be one of the following:
373
374 1. XML-descriptor (VERSION.xml file):
375
376 <version>
377 1.0
378 </version>
379
380 <headers>
381 /path1/to/header(s)/
382 /path2/to/header(s)/
383 ...
384 </headers>
385
386 <libs>
387 /path1/to/library(ies)/
388 /path2/to/library(ies)/
389 ...
390 </libs>
391
392 ... (XML-descriptor template
393 can be generated by -d option)
394
395 2. ABI dump generated by -dump option
396 3. Directory with headers and/or $SLIB_TYPE libraries
397 4. Single header file
398 5. Single $SLIB_TYPE library
399 6. Comma separated list of headers and/or libraries
400
401 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400402 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400403
404 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400405 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400406
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400407 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400408 Descriptor of 2nd (new) library version.
409
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400410 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400411 Create library ABI dump for the input XML descriptor. You can
412 transfer it anywhere and pass instead of the descriptor. Also
413 it can be used for debugging the tool.
414
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400415 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400416
417 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400418 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419
420sub HELP_MESSAGE() {
421 printMsg("INFO", $HelpMessage."
422MORE INFO:
423 $CmdName --info\n");
424}
425
426sub INFO_MESSAGE()
427{
428 printMsg("INFO", "$HelpMessage
429EXTRA OPTIONS:
430 -d|-descriptor-template
431 Create XML-descriptor template ./VERSION.xml
432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400433 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300434 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 for portability to the new library version.
436
437 -static-libs
438 Check static libraries instead of the shared ones. The <libs> section
439 of the XML-descriptor should point to static libraries location.
440
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400441 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400442 Path to the cross GCC compiler to use instead of the usual (host) GCC.
443
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400444 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400445 GCC toolchain prefix.
446
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400447 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400448 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400449 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400451 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400452 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200453 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400454
455 In general case you should specify it in the XML-descriptor:
456 <version>
457 VERSION
458 </version>
459
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400460 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400461 Specify 2nd library version outside the descriptor.
462
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400463 -vnum NUM
464 Specify the library version in the generated ABI dump. The <version> section
465 of the input XML descriptor will be overwritten in this case.
466
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400467 -s|-strict
468 Treat all compatibility warnings as problems. Add a number of \"Low\"
469 severity problems to the return value of the tool.
470
471 -headers-only
472 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
473 provide a low quality compatibility report with false positives and
474 without detecting of added/removed symbols.
475
476 Alternatively you can write \"none\" word to the <libs> section
477 in the XML-descriptor:
478 <libs>
479 none
480 </libs>
481
482 -objects-only
483 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
484 provide a low quality compatibility report with false positives and
485 without analysis of changes in parameters and data types.
486
487 Alternatively you can write \"none\" word to the <headers> section
488 in the XML-descriptor:
489 <headers>
490 none
491 </headers>
492
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400493 -show-retval
494 Show the symbol's return type in the report.
495
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400496 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300497 This option allows to specify a file with a list of symbols (mangled
498 names in C++) that should be checked. Other symbols will not be checked.
499
500 -types-list PATH
501 This option allows to specify a file with a list of types that should
502 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400503
504 -skip-symbols PATH
505 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400506
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400507 -headers-list PATH
508 The file with a list of headers, that should be checked/dumped.
509
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400510 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400511 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400512
513 -header NAME
514 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400515
516 -use-dumps
517 Make dumps for two versions of a library and compare dumps. This should
518 increase the performance of the tool and decrease the system memory usage.
519
520 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400521 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400522
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400523 -dump-system NAME -sysroot DIR
524 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400525 create XML descriptors and make ABI dumps for each library. The result
526 set of ABI dumps can be compared (--cmp-systems) with the other one
527 created for other version of operating system in order to check them for
528 compatibility. Do not forget to specify -cross-gcc option if your target
529 system requires some specific version of GCC compiler (different from
530 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400531 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400532
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400533 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400534 The same as the previous option but takes an XML descriptor of the target
535 system as input, where you should describe it:
536
537 /* Primary sections */
538
539 <name>
540 /* Name of the system */
541 </name>
542
543 <headers>
544 /* The list of paths to header files and/or
545 directories with header files, one per line */
546 </headers>
547
548 <libs>
549 /* The list of paths to shared libraries and/or
550 directories with shared libraries, one per line */
551 </libs>
552
553 /* Optional sections */
554
555 <search_headers>
556 /* List of directories to be searched
557 for header files to automatically
558 generate include paths, one per line */
559 </search_headers>
560
561 <search_libs>
562 /* List of directories to be searched
563 for shared libraries to resolve
564 dependencies, one per line */
565 </search_libs>
566
567 <tools>
568 /* List of directories with tools used
569 for analysis (GCC toolchain), one per line */
570 </tools>
571
572 <cross_prefix>
573 /* GCC toolchain prefix.
574 Examples:
575 arm-linux-gnueabi
576 arm-none-symbianelf */
577 </cross_prefix>
578
579 <gcc_options>
580 /* Additional GCC options, one per line */
581 </gcc_options>
582
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400583 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300584 This option should be used with -dump-system option to dump
585 ABI of operating systems and configure the dumping process.
586 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400587 modules/Targets/{unix, symbian, windows}
588
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400589 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400590 Compare two system ABI dumps. Create compatibility reports for each
591 library and the common HTML report including the summary of test
592 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400593 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400594
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400595 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400596 The file with a list of libraries, that should be dumped by
597 the -dump-system option or should be checked by the -cmp-systems option.
598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400599 -ext|-extended
600 If your library A is supposed to be used by other library B and you
601 want to control the ABI of B, then you should enable this option. The
602 tool will check for changes in all data types, even if they are not
603 used by any function in the library A. Such data types are not part
604 of the A library ABI, but may be a part of the ABI of the B library.
605
606 The short scheme is:
607 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
608
609 -q|-quiet
610 Print all messages to the file instead of stdout and stderr.
611 Default path (can be changed by -log-path option):
612 $COMMON_LOG_PATH
613
614 -stdout
615 Print analysis results (compatibility reports and ABI dumps) to stdout
616 instead of creating a file. This would allow piping data to other programs.
617
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400618 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400619 Change format of compatibility report.
620 Formats:
621 htm - HTML format (default)
622 xml - XML format
623
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400624 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400625 Change format of ABI dump.
626 Formats:
627 perl - Data::Dumper format (default)
628 xml - XML format
629
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400630 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400631 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400632
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400633 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400634 Set library language (C or C++). You can use this option if the tool
635 cannot auto-detect a language. This option may be useful for checking
636 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400637
638 -arch ARCH
639 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
640 ect.). The option is useful if the tool cannot detect correct architecture
641 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400642
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400643 -binary|-bin|-abi
644 Show \"Binary\" compatibility problems only.
645 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400646 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400647
648 -source|-src|-api
649 Show \"Source\" compatibility problems only.
650 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400651 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400652
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400653 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400654 The maximum number of affected symbols listed under the description
655 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400657OTHER OPTIONS:
658 -test
659 Run internal tests. Create two binary incompatible versions of a sample
660 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300661 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662
663 -test-dump
664 Test ability to create, read and compare ABI dumps.
665
666 -debug
667 Debugging mode. Print debug info on the screen. Save intermediate
668 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400669 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400670
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400671 Also consider using --dump option for debugging the tool.
672
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 If your header files are written in C language and can be compiled
675 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
676 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400677
678 -cpp-incompatible
679 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400682 Path to file with the function parameter names. It can be used
683 for improving report view if the library header files have no
684 parameter names. File format:
685
686 func1;param1;param2;param3 ...
687 func2;param1;param2;param3 ...
688 ...
689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -relpath PATH
691 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692 for dumping the library ABI (see -dump option).
693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -relpath1 PATH
695 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 -relpath2 PATH
698 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400701 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400705 -sort
706 Enable sorting of data in ABI dumps.
707
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400709 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400710 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400711 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400712
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400714 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400717
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400719 Path to \"Source\" compatibility report.
720 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400721 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400722
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724 Log path for all messages.
725 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400726 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400727
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400729 Log path for 1st version of a library.
730 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400732
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400733 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400734 Log path for 2nd version of a library.
735 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400736 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400737
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400738 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400739 Change logging mode.
740 Modes:
741 w - overwrite old logs (default)
742 a - append old logs
743 n - do not write any logs
744
745 -list-affected
746 Generate file with the list of incompatible
747 symbols beside the HTML compatibility report.
748 Use 'c++filt \@file' command from GNU binutils
749 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400750 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400751 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400752 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400753
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400754 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400755 The component name in the title and summary of the HTML report.
756 Default:
757 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300758
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400759 -l-full|-lib-full NAME
760 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400761 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400762
763 -extra-info DIR
764 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400765
766 -extra-dump
767 Create extended ABI dump containing all symbols
768 from the translation unit.
769
770 -force
771 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400772
773 -tolerance LEVEL
774 Apply a set of heuristics to successfully compile input
775 header files. You can enable several tolerance levels by
776 joining them into one string (e.g. 13, 124, etc.).
777 Levels:
778 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
779 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
780 3 - skip headers that iclude non-Linux headers
781 4 - skip headers included by others
782
783 -tolerant
784 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400785
786 -check
787 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400788
789 -quick
790 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400791
792 -skip-internal PATTERN
793 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400794
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400795REPORT:
796 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400797 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400798
799 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400800 logs/LIB_NAME/V1/log.txt
801 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400802
803EXIT CODES:
804 0 - Compatible. The tool has run without any errors.
805 non-zero - Incompatible or the tool has run with errors.
806
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400807MORE INFORMATION:
808 ".$HomePage{"Wiki"}."
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400809 ".$HomePage{"Dev"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400810}
811
812my $DescriptorTemplate = "
813<?xml version=\"1.0\" encoding=\"utf-8\"?>
814<descriptor>
815
816/* Primary sections */
817
818<version>
819 /* Version of the library */
820</version>
821
822<headers>
823 /* The list of paths to header files and/or
824 directories with header files, one per line */
825</headers>
826
827<libs>
828 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
829 directories with shared libraries, one per line */
830</libs>
831
832/* Optional sections */
833
834<include_paths>
835 /* The list of include paths that will be provided
836 to GCC to compile library headers, one per line.
837 NOTE: If you define this section then the tool
838 will not automatically generate include paths */
839</include_paths>
840
841<add_include_paths>
842 /* The list of include paths that will be added
843 to the automatically generated include paths, one per line */
844</add_include_paths>
845
846<skip_include_paths>
847 /* The list of include paths that will be removed from the
848 list of automatically generated include paths, one per line */
849</skip_include_paths>
850
851<gcc_options>
852 /* Additional GCC options, one per line */
853</gcc_options>
854
855<include_preamble>
856 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400857 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400858</include_preamble>
859
860<defines>
861 /* The list of defines that will be added at the
862 headers compiling stage, one per line:
863 #define A B
864 #define C D */
865</defines>
866
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400867<add_namespaces>
868 /* The list of namespaces that should be added to the alanysis
869 if the tool cannot find them automatically, one per line */
870</add_namespaces>
871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400872<skip_types>
873 /* The list of data types, that
874 should not be checked, one per line */
875</skip_types>
876
877<skip_symbols>
878 /* The list of functions (mangled/symbol names in C++),
879 that should not be checked, one per line */
880</skip_symbols>
881
882<skip_namespaces>
883 /* The list of C++ namespaces, that
884 should not be checked, one per line */
885</skip_namespaces>
886
887<skip_constants>
888 /* The list of constants that should
889 not be checked, one name per line */
890</skip_constants>
891
892<skip_headers>
893 /* The list of header files and/or directories
894 with header files that should not be checked, one per line */
895</skip_headers>
896
897<skip_libs>
898 /* The list of shared libraries and/or directories
899 with shared libraries that should not be checked, one per line */
900</skip_libs>
901
902<skip_including>
903 /* The list of header files, that cannot be included
904 directly (or non-self compiled ones), one per line */
905</skip_including>
906
907<search_headers>
908 /* List of directories to be searched
909 for header files to automatically
910 generate include paths, one per line. */
911</search_headers>
912
913<search_libs>
914 /* List of directories to be searched
915 for shared librariess to resolve
916 dependencies, one per line */
917</search_libs>
918
919<tools>
920 /* List of directories with tools used
921 for analysis (GCC toolchain), one per line */
922</tools>
923
924<cross_prefix>
925 /* GCC toolchain prefix.
926 Examples:
927 arm-linux-gnueabi
928 arm-none-symbianelf */
929</cross_prefix>
930
931</descriptor>";
932
933my %Operator_Indication = (
934 "not" => "~",
935 "assign" => "=",
936 "andassign" => "&=",
937 "orassign" => "|=",
938 "xorassign" => "^=",
939 "or" => "|",
940 "xor" => "^",
941 "addr" => "&",
942 "and" => "&",
943 "lnot" => "!",
944 "eq" => "==",
945 "ne" => "!=",
946 "lt" => "<",
947 "lshift" => "<<",
948 "lshiftassign" => "<<=",
949 "rshiftassign" => ">>=",
950 "call" => "()",
951 "mod" => "%",
952 "modassign" => "%=",
953 "subs" => "[]",
954 "land" => "&&",
955 "lor" => "||",
956 "rshift" => ">>",
957 "ref" => "->",
958 "le" => "<=",
959 "deref" => "*",
960 "mult" => "*",
961 "preinc" => "++",
962 "delete" => " delete",
963 "vecnew" => " new[]",
964 "vecdelete" => " delete[]",
965 "predec" => "--",
966 "postinc" => "++",
967 "postdec" => "--",
968 "plusassign" => "+=",
969 "plus" => "+",
970 "minus" => "-",
971 "minusassign" => "-=",
972 "gt" => ">",
973 "ge" => ">=",
974 "new" => " new",
975 "multassign" => "*=",
976 "divassign" => "/=",
977 "div" => "/",
978 "neg" => "-",
979 "pos" => "+",
980 "memref" => "->*",
981 "compound" => "," );
982
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400983my %UnknownOperator;
984
985my %NodeType= (
986 "array_type" => "Array",
987 "binfo" => "Other",
988 "boolean_type" => "Intrinsic",
989 "complex_type" => "Intrinsic",
990 "const_decl" => "Other",
991 "enumeral_type" => "Enum",
992 "field_decl" => "Other",
993 "function_decl" => "Other",
994 "function_type" => "FunctionType",
995 "identifier_node" => "Other",
996 "integer_cst" => "Other",
997 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400998 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400999 "method_type" => "MethodType",
1000 "namespace_decl" => "Other",
1001 "parm_decl" => "Other",
1002 "pointer_type" => "Pointer",
1003 "real_cst" => "Other",
1004 "real_type" => "Intrinsic",
1005 "record_type" => "Struct",
1006 "reference_type" => "Ref",
1007 "string_cst" => "Other",
1008 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001009 "template_type_parm" => "TemplateParam",
1010 "typename_type" => "TypeName",
1011 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001012 "tree_list" => "Other",
1013 "tree_vec" => "Other",
1014 "type_decl" => "Other",
1015 "union_type" => "Union",
1016 "var_decl" => "Other",
1017 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001018 "nop_expr" => "Other", #
1019 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001020 "offset_type" => "Other" );
1021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001022my %CppKeywords_C = map {$_=>1} (
1023 # C++ 2003 keywords
1024 "public",
1025 "protected",
1026 "private",
1027 "default",
1028 "template",
1029 "new",
1030 #"asm",
1031 "dynamic_cast",
1032 "auto",
1033 "try",
1034 "namespace",
1035 "typename",
1036 "using",
1037 "reinterpret_cast",
1038 "friend",
1039 "class",
1040 "virtual",
1041 "const_cast",
1042 "mutable",
1043 "static_cast",
1044 "export",
1045 # C++0x keywords
1046 "noexcept",
1047 "nullptr",
1048 "constexpr",
1049 "static_assert",
1050 "explicit",
1051 # cannot be used as a macro name
1052 # as it is an operator in C++
1053 "and",
1054 #"and_eq",
1055 "not",
1056 #"not_eq",
1057 "or"
1058 #"or_eq",
1059 #"bitand",
1060 #"bitor",
1061 #"xor",
1062 #"xor_eq",
1063 #"compl"
1064);
1065
1066my %CppKeywords_F = map {$_=>1} (
1067 "delete",
1068 "catch",
1069 "alignof",
1070 "thread_local",
1071 "decltype",
1072 "typeid"
1073);
1074
1075my %CppKeywords_O = map {$_=>1} (
1076 "bool",
1077 "register",
1078 "inline",
1079 "operator"
1080);
1081
1082my %CppKeywords_A = map {$_=>1} (
1083 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001084 "throw",
1085 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001086);
1087
1088foreach (keys(%CppKeywords_C),
1089keys(%CppKeywords_F),
1090keys(%CppKeywords_O)) {
1091 $CppKeywords_A{$_}=1;
1092}
1093
1094# Header file extensions as described by gcc
1095my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1096
1097my %IntrinsicMangling = (
1098 "void" => "v",
1099 "bool" => "b",
1100 "wchar_t" => "w",
1101 "char" => "c",
1102 "signed char" => "a",
1103 "unsigned char" => "h",
1104 "short" => "s",
1105 "unsigned short" => "t",
1106 "int" => "i",
1107 "unsigned int" => "j",
1108 "long" => "l",
1109 "unsigned long" => "m",
1110 "long long" => "x",
1111 "__int64" => "x",
1112 "unsigned long long" => "y",
1113 "__int128" => "n",
1114 "unsigned __int128" => "o",
1115 "float" => "f",
1116 "double" => "d",
1117 "long double" => "e",
1118 "__float80" => "e",
1119 "__float128" => "g",
1120 "..." => "z"
1121);
1122
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001123my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1124
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001125my %StdcxxMangling = (
1126 "3std"=>"St",
1127 "3std9allocator"=>"Sa",
1128 "3std12basic_string"=>"Sb",
1129 "3std12basic_stringIcE"=>"Ss",
1130 "3std13basic_istreamIcE"=>"Si",
1131 "3std13basic_ostreamIcE"=>"So",
1132 "3std14basic_iostreamIcE"=>"Sd"
1133);
1134
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001135my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001136my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1137
1138my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001139my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001141my %ConstantSuffix = (
1142 "unsigned int"=>"u",
1143 "long"=>"l",
1144 "unsigned long"=>"ul",
1145 "long long"=>"ll",
1146 "unsigned long long"=>"ull"
1147);
1148
1149my %ConstantSuffixR =
1150reverse(%ConstantSuffix);
1151
1152my %OperatorMangling = (
1153 "~" => "co",
1154 "=" => "aS",
1155 "|" => "or",
1156 "^" => "eo",
1157 "&" => "an",#ad (addr)
1158 "==" => "eq",
1159 "!" => "nt",
1160 "!=" => "ne",
1161 "<" => "lt",
1162 "<=" => "le",
1163 "<<" => "ls",
1164 "<<=" => "lS",
1165 ">" => "gt",
1166 ">=" => "ge",
1167 ">>" => "rs",
1168 ">>=" => "rS",
1169 "()" => "cl",
1170 "%" => "rm",
1171 "[]" => "ix",
1172 "&&" => "aa",
1173 "||" => "oo",
1174 "*" => "ml",#de (deref)
1175 "++" => "pp",#
1176 "--" => "mm",#
1177 "new" => "nw",
1178 "delete" => "dl",
1179 "new[]" => "na",
1180 "delete[]" => "da",
1181 "+=" => "pL",
1182 "+" => "pl",#ps (pos)
1183 "-" => "mi",#ng (neg)
1184 "-=" => "mI",
1185 "*=" => "mL",
1186 "/=" => "dV",
1187 "&=" => "aN",
1188 "|=" => "oR",
1189 "%=" => "rM",
1190 "^=" => "eO",
1191 "/" => "dv",
1192 "->*" => "pm",
1193 "->" => "pt",#rf (ref)
1194 "," => "cm",
1195 "?" => "qu",
1196 "." => "dt",
1197 "sizeof"=> "sz"#st
1198);
1199
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001200my %Intrinsic_Keywords = map {$_=>1} (
1201 "true",
1202 "false",
1203 "_Bool",
1204 "_Complex",
1205 "const",
1206 "int",
1207 "long",
1208 "void",
1209 "short",
1210 "float",
1211 "volatile",
1212 "restrict",
1213 "unsigned",
1214 "signed",
1215 "char",
1216 "double",
1217 "class",
1218 "struct",
1219 "union",
1220 "enum"
1221);
1222
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001223my %GlibcHeader = map {$_=>1} (
1224 "aliases.h",
1225 "argp.h",
1226 "argz.h",
1227 "assert.h",
1228 "cpio.h",
1229 "ctype.h",
1230 "dirent.h",
1231 "envz.h",
1232 "errno.h",
1233 "error.h",
1234 "execinfo.h",
1235 "fcntl.h",
1236 "fstab.h",
1237 "ftw.h",
1238 "glob.h",
1239 "grp.h",
1240 "iconv.h",
1241 "ifaddrs.h",
1242 "inttypes.h",
1243 "langinfo.h",
1244 "limits.h",
1245 "link.h",
1246 "locale.h",
1247 "malloc.h",
1248 "math.h",
1249 "mntent.h",
1250 "monetary.h",
1251 "nl_types.h",
1252 "obstack.h",
1253 "printf.h",
1254 "pwd.h",
1255 "regex.h",
1256 "sched.h",
1257 "search.h",
1258 "setjmp.h",
1259 "shadow.h",
1260 "signal.h",
1261 "spawn.h",
1262 "stdarg.h",
1263 "stdint.h",
1264 "stdio.h",
1265 "stdlib.h",
1266 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001267 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001268 "tar.h",
1269 "termios.h",
1270 "time.h",
1271 "ulimit.h",
1272 "unistd.h",
1273 "utime.h",
1274 "wchar.h",
1275 "wctype.h",
1276 "wordexp.h" );
1277
1278my %GlibcDir = map {$_=>1} (
1279 "arpa",
1280 "bits",
1281 "gnu",
1282 "netinet",
1283 "net",
1284 "nfs",
1285 "rpc",
1286 "sys",
1287 "linux" );
1288
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001289my %WinHeaders = map {$_=>1} (
1290 "dos.h",
1291 "process.h",
1292 "winsock.h",
1293 "config-win.h",
1294 "mem.h",
1295 "windows.h",
1296 "winsock2.h",
1297 "crtdbg.h",
1298 "ws2tcpip.h"
1299);
1300
1301my %ObsoleteHeaders = map {$_=>1} (
1302 "iostream.h",
1303 "fstream.h"
1304);
1305
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001306my %AlienHeaders = map {$_=>1} (
1307 # Solaris
1308 "thread.h",
1309 "sys/atomic.h",
1310 # HPUX
1311 "sys/stream.h",
1312 # Symbian
1313 "AknDoc.h",
1314 # Atari ST
1315 "ext.h",
1316 "tos.h",
1317 # MS-DOS
1318 "alloc.h",
1319 # Sparc
1320 "sys/atomic.h"
1321);
1322
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001323my %ConfHeaders = map {$_=>1} (
1324 "atomic",
1325 "conf.h",
1326 "config.h",
1327 "configure.h",
1328 "build.h",
1329 "setup.h"
1330);
1331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001332my %LocalIncludes = map {$_=>1} (
1333 "/usr/local/include",
1334 "/usr/local" );
1335
1336my %OS_AddPath=(
1337# These paths are needed if the tool cannot detect them automatically
1338 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001339 "include"=>[
1340 "/Library",
1341 "/Developer/usr/include"
1342 ],
1343 "lib"=>[
1344 "/Library",
1345 "/Developer/usr/lib"
1346 ],
1347 "bin"=>[
1348 "/Developer/usr/bin"
1349 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001350 },
1351 "beos"=>{
1352 # Haiku has GCC 2.95.3 by default
1353 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001354 "include"=>[
1355 "/boot/common",
1356 "/boot/develop"
1357 ],
1358 "lib"=>[
1359 "/boot/common/lib",
1360 "/boot/system/lib",
1361 "/boot/apps"
1362 ],
1363 "bin"=>[
1364 "/boot/common/bin",
1365 "/boot/system/bin",
1366 "/boot/develop/abi"
1367 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001369);
1370
1371my %Slash_Type=(
1372 "default"=>"/",
1373 "windows"=>"\\"
1374);
1375
1376my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1377
1378# Global Variables
1379my %COMMON_LANGUAGE=(
1380 1 => "C",
1381 2 => "C" );
1382
1383my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001384my $MAX_CPPFILT_FILE_SIZE = 50000;
1385my $CPPFILT_SUPPORT_FILE;
1386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001387my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1388
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001389my $STDCXX_TESTING = 0;
1390my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001391my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001392
1393my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1394my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001395
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001396my $TargetComponent;
1397
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001398my $CheckUndefined = 0;
1399
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001400# Set Target Component Name
1401if($TargetComponent_Opt) {
1402 $TargetComponent = lc($TargetComponent_Opt);
1403}
1404else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001405{ # default: library
1406 # other components: header, system, ...
1407 $TargetComponent = "library";
1408}
1409
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001410my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001412my $SystemRoot;
1413
1414my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001415my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001416my %LOG_PATH;
1417my %DEBUG_PATH;
1418my %Cache;
1419my %LibInfo;
1420my $COMPILE_ERRORS = 0;
1421my %CompilerOptions;
1422my %CheckedDyLib;
1423my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1424
1425# Constants (#defines)
1426my %Constants;
1427my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001428my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001429
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001430# Extra Info
1431my %SymbolHeader;
1432my %KnownLibs;
1433
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001434# Templates
1435my %TemplateInstance;
1436my %BasicTemplate;
1437my %TemplateArg;
1438my %TemplateDecl;
1439my %TemplateMap;
1440
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001441# Types
1442my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001443my %SkipTypes = (
1444 "1"=>{},
1445 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446my %CheckedTypes;
1447my %TName_Tid;
1448my %EnumMembName_Id;
1449my %NestedNameSpaces = (
1450 "1"=>{},
1451 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001453my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001454my %ClassVTable;
1455my %ClassVTable_Content;
1456my %VTableClass;
1457my %AllocableClass;
1458my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001459my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001460my %Class_SubClasses;
1461my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001462my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001463my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001464
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001465my %CheckedTypeInfo;
1466
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001467# Typedefs
1468my %Typedef_BaseName;
1469my %Typedef_Tr;
1470my %Typedef_Eq;
1471my %StdCxxTypedef;
1472my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001473my %MissedBase;
1474my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001475my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001476
1477# Symbols
1478my %SymbolInfo;
1479my %tr_name;
1480my %mangled_name_gcc;
1481my %mangled_name;
1482my %SkipSymbols = (
1483 "1"=>{},
1484 "2"=>{} );
1485my %SkipNameSpaces = (
1486 "1"=>{},
1487 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001488my %AddNameSpaces = (
1489 "1"=>{},
1490 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001492my %TypesList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001493my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001494my %SymbolsList_App;
1495my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001496my %Symbol_Library = (
1497 "1"=>{},
1498 "2"=>{} );
1499my %Library_Symbol = (
1500 "1"=>{},
1501 "2"=>{} );
1502my %DepSymbol_Library = (
1503 "1"=>{},
1504 "2"=>{} );
1505my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506 "1"=>{},
1507 "2"=>{} );
1508my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001509my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001510my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001511my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001512my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001513my %Library_Needed= (
1514 "1"=>{},
1515 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001516
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001517# Extra Info
1518my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001519my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001520
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001521# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001522my %Include_Preamble = (
1523 "1"=>[],
1524 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001526my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001527my %HeaderName_Paths;
1528my %Header_Dependency;
1529my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001530my %Include_Paths = (
1531 "1"=>[],
1532 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001533my %INC_PATH_AUTODETECT = (
1534 "1"=>1,
1535 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001536my %Add_Include_Paths = (
1537 "1"=>[],
1538 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001539my %Skip_Include_Paths;
1540my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001541my %Header_ErrorRedirect;
1542my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001543my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001544my %Header_ShouldNotBeUsed;
1545my %RecursiveIncludes;
1546my %Header_Include_Prefix;
1547my %SkipHeaders;
1548my %SkipHeadersList=(
1549 "1"=>{},
1550 "2"=>{} );
1551my %SkipLibs;
1552my %Include_Order;
1553my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001554my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001555my %TUnit_Funcs;
1556my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001557
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001558my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001559 "1"=>0,
1560 "2"=>0 );
1561my %AutoPreambleMode = (
1562 "1"=>0,
1563 "2"=>0 );
1564my %MinGWMode = (
1565 "1"=>0,
1566 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001567my %Cpp0xMode = (
1568 "1"=>0,
1569 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001570
1571# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001572my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001573my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001574my %RegisteredSONAMEs;
1575my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001576
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001577my %CheckedArch;
1578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579# System Objects
1580my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001581my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001582my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001583
1584# System Headers
1585my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001586my @DefaultCppPaths;
1587my @DefaultGccPaths;
1588my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001589my %DefaultCppHeader;
1590my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001591my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001592
1593# Merging
1594my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001595my $Version;
1596my %AddedInt;
1597my %RemovedInt;
1598my %AddedInt_Virt;
1599my %RemovedInt_Virt;
1600my %VirtualReplacement;
1601my %ChangedTypedef;
1602my %CompatRules;
1603my %IncompleteRules;
1604my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001605my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001606my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001607my %ReturnedClass;
1608my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001609my %SourceAlternative;
1610my %SourceAlternative_B;
1611my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001612my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001613
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001614# Calling Conventions
1615my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001616 1=>{ "R"=>0, "P"=>0 },
1617 2=>{ "R"=>0, "P"=>0 }
1618);
1619
1620# ABI Dump
1621my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001623# OS Compliance
1624my %TargetLibs;
1625my %TargetHeaders;
1626
1627# OS Specifics
1628my $OStarget = $OSgroup;
1629my %TargetTools;
1630
1631# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001632my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001633
1634# Recursion locks
1635my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001636my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001637my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001638my @RecurInclude;
1639my @RecurConstant;
1640
1641# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001642my %SystemPaths = (
1643 "include"=>[],
1644 "lib"=>[],
1645 "bin"=>[]
1646);
1647my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001648my $GCC_PATH;
1649
1650# Symbols versioning
1651my %SymVer = (
1652 "1"=>{},
1653 "2"=>{} );
1654
1655# Problem descriptions
1656my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001657my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001658my %TotalAffected;
1659
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001660# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001661my $ContentID = 1;
1662my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1663my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1664my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1665my $ContentSpanEnd = "</span>\n";
1666my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1667my $ContentDivEnd = "</div>\n";
1668my $Content_Counter = 0;
1669
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001670# Modes
1671my $JoinReport = 1;
1672my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001673
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001674my %Severity_Val=(
1675 "High"=>3,
1676 "Medium"=>2,
1677 "Low"=>1,
1678 "Safe"=>-1
1679);
1680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001681sub get_Modules()
1682{
1683 my $TOOL_DIR = get_dirname($0);
1684 if(not $TOOL_DIR)
1685 { # patch for MS Windows
1686 $TOOL_DIR = ".";
1687 }
1688 my @SEARCH_DIRS = (
1689 # tool's directory
1690 abs_path($TOOL_DIR),
1691 # relative path to modules
1692 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001693 # install path
1694 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001695 );
1696 foreach my $DIR (@SEARCH_DIRS)
1697 {
1698 if(not is_abs($DIR))
1699 { # relative path
1700 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1701 }
1702 if(-d $DIR."/modules") {
1703 return $DIR."/modules";
1704 }
1705 }
1706 exitStatus("Module_Error", "can't find modules");
1707}
1708
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001709my %LoadedModules = ();
1710
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001711sub loadModule($)
1712{
1713 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001714 if(defined $LoadedModules{$Name}) {
1715 return;
1716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001717 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1718 if(not -f $Path) {
1719 exitStatus("Module_Error", "can't access \'$Path\'");
1720 }
1721 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001722 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001723}
1724
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001725sub readModule($$)
1726{
1727 my ($Module, $Name) = @_;
1728 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1729 if(not -f $Path) {
1730 exitStatus("Module_Error", "can't access \'$Path\'");
1731 }
1732 return readFile($Path);
1733}
1734
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001735sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001736{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001737 my $Number = $_[0];
1738 if(not $Number) {
1739 $Number = 1;
1740 }
1741 else {
1742 $Number = int($Number)+1;
1743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001744 if($Number>3) {
1745 return $Number."th";
1746 }
1747 elsif($Number==1) {
1748 return "1st";
1749 }
1750 elsif($Number==2) {
1751 return "2nd";
1752 }
1753 elsif($Number==3) {
1754 return "3rd";
1755 }
1756 else {
1757 return $Number;
1758 }
1759}
1760
1761sub search_Tools($)
1762{
1763 my $Name = $_[0];
1764 return "" if(not $Name);
1765 if(my @Paths = keys(%TargetTools))
1766 {
1767 foreach my $Path (@Paths)
1768 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001769 if(-f join_P($Path, $Name)) {
1770 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001771 }
1772 if($CrossPrefix)
1773 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001774 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001775 if(-f $Candidate) {
1776 return $Candidate;
1777 }
1778 }
1779 }
1780 }
1781 else {
1782 return "";
1783 }
1784}
1785
1786sub synch_Cmd($)
1787{
1788 my $Name = $_[0];
1789 if(not $GCC_PATH)
1790 { # GCC was not found yet
1791 return "";
1792 }
1793 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001794 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001795 return $Candidate;
1796 }
1797 return "";
1798}
1799
1800sub get_CmdPath($)
1801{
1802 my $Name = $_[0];
1803 return "" if(not $Name);
1804 if(defined $Cache{"get_CmdPath"}{$Name}) {
1805 return $Cache{"get_CmdPath"}{$Name};
1806 }
1807 my %BinUtils = map {$_=>1} (
1808 "c++filt",
1809 "objdump",
1810 "readelf"
1811 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001812 if($BinUtils{$Name} and $GCC_PATH)
1813 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 if(my $Dir = get_dirname($GCC_PATH)) {
1815 $TargetTools{$Dir}=1;
1816 }
1817 }
1818 my $Path = search_Tools($Name);
1819 if(not $Path and $OSgroup eq "windows") {
1820 $Path = search_Tools($Name.".exe");
1821 }
1822 if(not $Path and $BinUtils{$Name})
1823 {
1824 if($CrossPrefix)
1825 { # user-defined prefix
1826 $Path = search_Cmd($CrossPrefix."-".$Name);
1827 }
1828 }
1829 if(not $Path and $BinUtils{$Name})
1830 {
1831 if(my $Candidate = synch_Cmd($Name))
1832 { # synch with GCC
1833 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001834 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001835 if(-f $Candidate) {
1836 $Path = $Candidate;
1837 }
1838 }
1839 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001840 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001841 $Path = $Candidate;
1842 }
1843 }
1844 }
1845 if(not $Path) {
1846 $Path = search_Cmd($Name);
1847 }
1848 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001849 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001850 $Path=search_Cmd($Name.".exe");
1851 }
1852 if($Path=~/\s/) {
1853 $Path = "\"".$Path."\"";
1854 }
1855 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1856}
1857
1858sub search_Cmd($)
1859{
1860 my $Name = $_[0];
1861 return "" if(not $Name);
1862 if(defined $Cache{"search_Cmd"}{$Name}) {
1863 return $Cache{"search_Cmd"}{$Name};
1864 }
1865 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1866 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1867 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001868 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001869 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001870 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 if(-f $CmdPath)
1872 {
1873 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001874 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 }
1876 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1877 }
1878 }
1879 return ($Cache{"search_Cmd"}{$Name} = "");
1880}
1881
1882sub get_CmdPath_Default($)
1883{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001884 return "" if(not $_[0]);
1885 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1886 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001888 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1889}
1890
1891sub get_CmdPath_Default_I($)
1892{ # search in PATH
1893 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 if($Name=~/find/)
1895 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001896 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001897 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898 }
1899 }
1900 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001901 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001902 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001903 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001904 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001906 if($OSgroup eq "windows")
1907 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001908 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001909 return $Name;
1910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001912 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001913 {
1914 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001915 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001916 }
1917 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001918 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919}
1920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001921sub classifyPath($)
1922{
1923 my $Path = $_[0];
1924 if($Path=~/[\*\[]/)
1925 { # wildcard
1926 $Path=~s/\*/.*/g;
1927 $Path=~s/\\/\\\\/g;
1928 return ($Path, "Pattern");
1929 }
1930 elsif($Path=~/[\/\\]/)
1931 { # directory or relative path
1932 return (path_format($Path, $OSgroup), "Path");
1933 }
1934 else {
1935 return ($Path, "Name");
1936 }
1937}
1938
1939sub readDescriptor($$)
1940{
1941 my ($LibVersion, $Content) = @_;
1942 return if(not $LibVersion);
1943 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1944 if(not $Content) {
1945 exitStatus("Error", "$DName is empty");
1946 }
1947 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001948 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001949 }
1950 $Content=~s/\/\*(.|\n)+?\*\///g;
1951 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001953 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1954 if($TargetVersion{$LibVersion}) {
1955 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1956 }
1957 if(not $Descriptor{$LibVersion}{"Version"}) {
1958 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1959 }
1960 if($Content=~/{RELPATH}/)
1961 {
1962 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1963 $Content =~ s/{RELPATH}/$RelDir/g;
1964 }
1965 else
1966 {
1967 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1968 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1969 }
1970 }
1971
1972 if(not $CheckObjectsOnly_Opt)
1973 {
1974 my $DHeaders = parseTag(\$Content, "headers");
1975 if(not $DHeaders) {
1976 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1977 }
1978 elsif(lc($DHeaders) ne "none")
1979 { # append the descriptor headers list
1980 if($Descriptor{$LibVersion}{"Headers"})
1981 { # multiple descriptors
1982 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1983 }
1984 else {
1985 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1986 }
1987 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1988 {
1989 if(not -e $Path) {
1990 exitStatus("Access_Error", "can't access \'$Path\'");
1991 }
1992 }
1993 }
1994 }
1995 if(not $CheckHeadersOnly_Opt)
1996 {
1997 my $DObjects = parseTag(\$Content, "libs");
1998 if(not $DObjects) {
1999 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
2000 }
2001 elsif(lc($DObjects) ne "none")
2002 { # append the descriptor libraries list
2003 if($Descriptor{$LibVersion}{"Libs"})
2004 { # multiple descriptors
2005 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
2006 }
2007 else {
2008 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
2009 }
2010 foreach my $Path (split(/\s*\n\s*/, $DObjects))
2011 {
2012 if(not -e $Path) {
2013 exitStatus("Access_Error", "can't access \'$Path\'");
2014 }
2015 }
2016 }
2017 }
2018 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
2019 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002020 if(not -d $Path) {
2021 exitStatus("Access_Error", "can't access directory \'$Path\'");
2022 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002023 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002024 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002025 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002026 }
2027 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2028 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 if(not -d $Path) {
2030 exitStatus("Access_Error", "can't access directory \'$Path\'");
2031 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002032 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002033 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002034 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 }
2036 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
2037 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002038 if(not -d $Path) {
2039 exitStatus("Access_Error", "can't access directory \'$Path\'");
2040 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002041 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002042 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002043 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002044 $TargetTools{$Path}=1;
2045 }
2046 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2047 $CrossPrefix = $Prefix;
2048 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002049 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2051 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002052 if(not -d $Path) {
2053 exitStatus("Access_Error", "can't access directory \'$Path\'");
2054 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002055 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002056 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002057 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002058 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002059 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2061 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002062 if(not -d $Path) {
2063 exitStatus("Access_Error", "can't access directory \'$Path\'");
2064 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002065 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002066 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002067 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002068 }
2069 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002070 { # skip some auto-generated include paths
2071 if(not is_abs($Path))
2072 {
2073 if(my $P = abs_path($Path)) {
2074 $Path = $P;
2075 }
2076 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002077 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002078 }
2079 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002080 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002081 my ($CPath, $Type) = classifyPath($Path);
2082 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002083 }
2084 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002085 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2086 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002087 if($Option!~/\A\-(Wl|l|L)/)
2088 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002089 $CompilerOptions{$LibVersion} .= " ".$Option;
2090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002091 }
2092 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2093 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2094 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002095 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002096 my ($CPath, $Type) = classifyPath($Path);
2097 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002098 }
2099 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2100 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2101 {
2102 my ($CPath, $Type) = classifyPath($Path);
2103 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2104 }
2105 if(my $DDefines = parseTag(\$Content, "defines"))
2106 {
2107 if($Descriptor{$LibVersion}{"Defines"})
2108 { # multiple descriptors
2109 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2110 }
2111 else {
2112 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2113 }
2114 }
2115 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2116 {
2117 if($Order=~/\A(.+):(.+)\Z/) {
2118 $Include_Order{$LibVersion}{$1} = $2;
2119 }
2120 }
2121 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2122 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002123 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002124 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2125 }
2126 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2127 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002128 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002129 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2130 }
2131 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2132 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2133 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002134 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2135 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002137 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2138 $SkipConstants{$LibVersion}{$Constant} = 1;
2139 }
2140 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2141 {
2142 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002143 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002144 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2145 }
2146 else {
2147 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2148 }
2149 }
2150}
2151
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002152sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002153{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002154 my $CodeRef = shift(@_);
2155 my $Tag = shift(@_);
2156 if(not $Tag or not $CodeRef) {
2157 return undef;
2158 }
2159 my $Sp = 0;
2160 if(@_) {
2161 $Sp = shift(@_);
2162 }
2163 my $Start = index(${$CodeRef}, "<$Tag>");
2164 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002165 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002166 my $End = index(${$CodeRef}, "</$Tag>");
2167 if($End!=-1)
2168 {
2169 my $TS = length($Tag)+3;
2170 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2171 substr($Content, 0, $TS-1, ""); # cut start tag
2172 substr($Content, -$TS, $TS, ""); # cut end tag
2173 if(not $Sp)
2174 {
2175 $Content=~s/\A\s+//g;
2176 $Content=~s/\s+\Z//g;
2177 }
2178 if(substr($Content, 0, 1) ne "<") {
2179 $Content = xmlSpecChars_R($Content);
2180 }
2181 return $Content;
2182 }
2183 }
2184 return undef;
2185}
2186
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002187sub getInfo($)
2188{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002189 my $DumpPath = $_[0];
2190 return if(not $DumpPath or not -f $DumpPath);
2191
2192 readTUDump($DumpPath);
2193
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002194 # processing info
2195 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002196
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002197 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002198 setAnonTypedef_All();
2199 }
2200
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002201 getTypeInfo_All();
2202 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002203 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002204 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002205 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002206
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002207 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002208 %LibInfo = ();
2209 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002210 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002211 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002212 %TemplateDecl = ();
2213 %StdCxxTypedef = ();
2214 %MissedTypedef = ();
2215 %Typedef_Tr = ();
2216 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002217 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002218
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002219 # clean cache
2220 delete($Cache{"getTypeAttr"});
2221 delete($Cache{"getTypeDeclId"});
2222
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002223 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002224 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002225 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002226 }
2227 else
2228 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002229 if($BinaryOnly and not $ExtendedCheck)
2230 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002231 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002232 }
2233 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002234 remove_Unused($Version, "Extended");
2235 }
2236 }
2237
2238 if($CheckInfo)
2239 {
2240 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2241 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2242 }
2243
2244 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2245 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002246 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002247 }
2248
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002249 if($Debug) {
2250 # debugMangling($Version);
2251 }
2252}
2253
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002254sub readTUDump($)
2255{
2256 my $DumpPath = $_[0];
2257
2258 open(TU_DUMP, $DumpPath);
2259 local $/ = undef;
2260 my $Content = <TU_DUMP>;
2261 close(TU_DUMP);
2262
2263 unlink($DumpPath);
2264
2265 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002266 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002267
2268 # clean memory
2269 undef $Content;
2270
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002271 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002272
2273 foreach (0 .. $#Lines)
2274 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002275 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002276 { # get a number and attributes of a node
2277 next if(not $NodeType{$2});
2278 $LibInfo{$Version}{"info_type"}{$1}=$2;
2279 $LibInfo{$Version}{"info"}{$1}=$3;
2280 }
2281
2282 # clean memory
2283 delete($Lines[$_]);
2284 }
2285
2286 # clean memory
2287 undef @Lines;
2288}
2289
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002290sub simplifyConstants()
2291{
2292 foreach my $Constant (keys(%{$Constants{$Version}}))
2293 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002294 if(defined $Constants{$Version}{$Constant}{"Header"})
2295 {
2296 my $Value = $Constants{$Version}{$Constant}{"Value"};
2297 if(defined $EnumConstants{$Version}{$Value}) {
2298 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2299 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002300 }
2301 }
2302}
2303
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002304sub simplifyNames()
2305{
2306 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2307 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002308 if($Typedef_Eq{$Version}{$Base}) {
2309 next;
2310 }
2311 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2312 if($#Translations==0)
2313 {
2314 if(length($Translations[0])<=length($Base)) {
2315 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2316 }
2317 }
2318 else
2319 { # select most appropriate
2320 foreach my $Tr (@Translations)
2321 {
2322 if($Base=~/\A\Q$Tr\E/)
2323 {
2324 $Typedef_Eq{$Version}{$Base} = $Tr;
2325 last;
2326 }
2327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002328 }
2329 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002330 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002331 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002332 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002333 if(not $TypeName) {
2334 next;
2335 }
2336 next if(index($TypeName,"<")==-1);# template instances only
2337 if($TypeName=~/>(::\w+)+\Z/)
2338 { # skip unused types
2339 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002340 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002341 foreach my $Base (sort {length($b)<=>length($a)}
2342 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002343 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002344 next if(not $Base);
2345 next if(index($TypeName,$Base)==-1);
2346 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002347 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002348 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002349 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2350 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2351 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002352 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002353 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2354 {
2355 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2356 {
2357 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2358 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002359 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002360 }
2361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002364 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002365 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002366 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2367 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002368 }
2369}
2370
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002371sub setAnonTypedef_All()
2372{
2373 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2374 {
2375 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2376 {
2377 if(isAnon(getNameByInfo($InfoId))) {
2378 $TypedefToAnon{getTypeId($InfoId)} = 1;
2379 }
2380 }
2381 }
2382}
2383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002384sub setTemplateParams_All()
2385{
2386 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2387 {
2388 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2389 setTemplateParams($_);
2390 }
2391 }
2392}
2393
2394sub setTemplateParams($)
2395{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002396 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002397 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002398 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002399 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002400 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002401 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002402 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002403 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002404 setTemplateInstParams($_[0], $TmplInst_Id);
2405 }
2406 }
2407
2408 $BasicTemplate{$Version}{$Tid} = $_[0];
2409
2410 if(my $Prms = getTreeAttr_Prms($_[0]))
2411 {
2412 if(my $Valu = getTreeAttr_Valu($Prms))
2413 {
2414 my $Vector = getTreeVec($Valu);
2415 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2416 {
2417 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2418 {
2419 if(my $Name = getNameByInfo($Val))
2420 {
2421 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2422 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2423 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2424 }
2425 else {
2426 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2427 }
2428 }
2429 }
2430 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002432 }
2433 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002434 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002435 {
2436 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2437 {
2438 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002439 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002440 }
2441 }
2442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002443}
2444
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002445sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002446{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002447 my ($Tmpl, $Inst) = @_;
2448
2449 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002450 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002451 my ($Params_InfoId, $ElemId) = ();
2452 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2453 $Params_InfoId = $1;
2454 }
2455 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2456 $ElemId = $1;
2457 }
2458 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002459 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002460 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2461 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2462 {
2463 my ($PPos, $PTypeId) = ($1, $2);
2464 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2465 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002466 if($PType eq "template_type_parm") {
2467 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002468 }
2469 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002470 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2471 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002472 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002473 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002474 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002475 else
2476 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002477 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002478 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002480 }
2481 }
2482 }
2483}
2484
2485sub getTypeDeclId($)
2486{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002487 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002488 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002489 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2490 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2491 }
2492 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2493 {
2494 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2495 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2496 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002498 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002499 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002500}
2501
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002502sub getTypeInfo_All()
2503{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002504 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002505 { # support for GCC < 4.5
2506 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2507 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2508 # FIXME: check GCC versions
2509 addMissedTypes_Pre();
2510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002512 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002513 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002514 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2515 if($IType=~/_type\Z/ and $IType ne "function_type"
2516 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002517 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002518 }
2519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002520
2521 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002522 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002523 "Name" => "...",
2524 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002525 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002526 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002527 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002528
2529 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002530 { # support for GCC < 4.5
2531 addMissedTypes_Post();
2532 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002533
2534 if($ADD_TMPL_INSTANCES)
2535 {
2536 # templates
2537 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2538 {
2539 if(defined $TemplateMap{$Version}{$Tid}
2540 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2541 {
2542 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2543 {
2544 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2545 {
2546 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2547 {
2548 if(my %MAttr = getTypeAttr($MembTypeId))
2549 {
2550 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2551 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2552 }
2553 }
2554 }
2555 }
2556 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2557 {
2558 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2559 {
2560 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2561
2562 if($NBid ne $Bid)
2563 {
2564 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2565 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2566 }
2567 }
2568 }
2569 }
2570 }
2571 }
2572}
2573
2574sub createType($$)
2575{
2576 my ($Attr, $LibVersion) = @_;
2577 my $NewId = ++$MAX_ID;
2578
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002579 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002580 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002581 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002582
2583 return "$NewId";
2584}
2585
2586sub instType($$$)
2587{ # create template instances
2588 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002589
2590 if(not $TypeInfo{$LibVersion}{$Tid}) {
2591 return undef;
2592 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002593 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2594
2595 foreach my $Key (sort keys(%{$Map}))
2596 {
2597 if(my $Val = $Map->{$Key})
2598 {
2599 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2600
2601 if(defined $Attr->{"NameSpace"}) {
2602 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2603 }
2604 foreach (keys(%{$Attr->{"TParam"}})) {
2605 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2606 }
2607 }
2608 else
2609 { # remove absent
2610 # _Traits, etc.
2611 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002612 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002613 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2614 }
2615 foreach (keys(%{$Attr->{"TParam"}}))
2616 {
2617 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2618 delete($Attr->{"TParam"}{$_});
2619 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002620 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002621 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2622 }
2623 }
2624 }
2625 }
2626
2627 my $Tmpl = 0;
2628
2629 if(defined $Attr->{"TParam"})
2630 {
2631 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2632 {
2633 my $PName = $Attr->{"TParam"}{$_}{"name"};
2634
2635 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2636 {
2637 my %Base = get_BaseType($PTid, $LibVersion);
2638
2639 if($Base{"Type"} eq "TemplateParam"
2640 or defined $Base{"Template"})
2641 {
2642 $Tmpl = 1;
2643 last
2644 }
2645 }
2646 }
2647 }
2648
2649 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2650 return "$Id";
2651 }
2652 else
2653 {
2654 if(not $Tmpl) {
2655 delete($Attr->{"Template"});
2656 }
2657
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002658 my $New = createType($Attr, $LibVersion);
2659
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002660 my %EMap = ();
2661 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2662 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2663 }
2664 foreach (keys(%{$Map})) {
2665 $EMap{$_} = $Map->{$_};
2666 }
2667
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002668 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2669 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002670 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002671 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002672 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002673 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002674 {
2675 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2676
2677 if($NBid ne $Bid)
2678 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002679 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2680 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002681 }
2682 }
2683 }
2684
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002685 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002686 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002687 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2688 {
2689 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2690 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2691 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002692 }
2693 }
2694
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002695 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002696 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002697 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2698 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002699 }
2700 }
2701
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002702 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2703 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002704 }
2705
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002706 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708}
2709
2710sub addMissedTypes_Pre()
2711{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002712 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002713 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2714 { # detecting missed typedefs
2715 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2716 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002717 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002719 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002720 if($TypeType eq "Unknown")
2721 { # template_type_parm
2722 next;
2723 }
2724 my $TypeDeclId = getTypeDeclId($TypeId);
2725 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2726 my $TypedefName = getNameByInfo($MissedTDid);
2727 next if(not $TypedefName);
2728 next if($TypedefName eq "__float80");
2729 next if(isAnon($TypedefName));
2730 if(not $TypeDeclId
2731 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002732 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002733 }
2734 }
2735 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002736 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002737 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002738 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002739 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002741 next;
2742 }
2743 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002745 if(not $TypedefName) {
2746 next;
2747 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002748 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 my %MissedInfo = ( # typedef info
2750 "Name" => $TypedefName,
2751 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002752 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002753 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002754 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 my ($H, $L) = getLocation($MissedTDid);
2756 $MissedInfo{"Header"} = $H;
2757 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002758 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002759 { # other types
2760 next;
2761 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002762 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002763 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002764 next;
2765 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002766 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002768 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002769 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002770 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002771 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002772 next;
2773 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002774 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002775 next;
2776 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002777 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 next;
2780 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002781 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002782 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002783 next;
2784 }
2785 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002786
2787 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2788
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002789 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002790 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002791 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002792 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002793 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002794
2795 # add missed & remove other
2796 $TypeInfo{$Version} = \%AddTypes;
2797 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002798}
2799
2800sub addMissedTypes_Post()
2801{
2802 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2803 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002804 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2805 {
2806 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2807 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2808 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2809 }
2810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002811 }
2812}
2813
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002814sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002815{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002816 my $TypeId = $_[0];
2817 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2818 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002819 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002820 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002822}
2823
2824sub getArraySize($$)
2825{
2826 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002827 if(my $Size = getSize($TypeId))
2828 {
2829 my $Elems = $Size/$BYTE_SIZE;
2830 while($BaseName=~s/\s*\[(\d+)\]//) {
2831 $Elems/=$1;
2832 }
2833 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2834 {
2835 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2836 $Elems/=$BasicSize;
2837 }
2838 }
2839 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002840 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002841 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002842}
2843
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002844sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002845{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002846 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002847 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002848 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2849 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002850 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002851 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2852 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2853 if(not $NodeType)
2854 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002855 return ();
2856 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002857 if($NodeType eq "tree_vec")
2858 {
2859 if($Pos!=$#Positions)
2860 { # select last vector of parameters ( ns<P1>::type<P2> )
2861 next;
2862 }
2863 }
2864 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2865 foreach my $P (@Params)
2866 {
2867 if($P eq "") {
2868 return ();
2869 }
2870 elsif($P ne "\@skip\@") {
2871 @TmplParams = (@TmplParams, $P);
2872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002873 }
2874 }
2875 return @TmplParams;
2876}
2877
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002879{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002880 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002881 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 if(defined $TypeInfo{$Version}{$TypeId}
2883 and $TypeInfo{$Version}{$TypeId}{"Name"})
2884 { # already created
2885 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002886 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002887 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2888 { # incomplete type
2889 return ();
2890 }
2891 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2892
2893 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002894 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002895
2896 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2897 {
2898 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2899 {
2900 if($Info=~/qual[ ]*:/)
2901 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002902 my $NewId = ++$MAX_ID;
2903
2904 $MissedBase{$Version}{$TypeId} = "$NewId";
2905 $MissedBase_R{$Version}{$NewId} = $TypeId;
2906 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2907 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002908 }
2909 }
2910 $TypeAttr{"Type"} = "Typedef";
2911 }
2912 else {
2913 $TypeAttr{"Type"} = getTypeType($TypeId);
2914 }
2915
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002916 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2917 {
2918 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2919 { # local code
2920 return ();
2921 }
2922 }
2923
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002924 if($TypeAttr{"Type"} eq "Unknown") {
2925 return ();
2926 }
2927 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2928 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002929 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002930 if(my $TName = $TypeAttr{"Name"})
2931 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002932 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002933 $TName_Tid{$Version}{$TName} = $TypeId;
2934 return %TypeAttr;
2935 }
2936 else {
2937 return ();
2938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002939 }
2940 elsif($TypeAttr{"Type"} eq "Array")
2941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2943 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002944 return ();
2945 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002946 if(my $Algn = getAlgn($TypeId)) {
2947 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002949 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002950 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002951 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002952 if(not $BTAttr{"Name"}) {
2953 return ();
2954 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002956 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002957 if(my $Size = getSize($TypeId)) {
2958 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2959 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002961 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2962 }
2963 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002964 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002966 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002967 else
2968 {
2969 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002971 $TypeAttr{"Name"} = $1."[]".$2;
2972 }
2973 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002974 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002976 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002977 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002978 if($BTAttr{"Header"}) {
2979 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002980 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002981 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002982 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2983 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002984 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002985 return ();
2986 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002987 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002988 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002989 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002990 if($TypeAttr{"Name"})
2991 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002992 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002993
2994 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2995 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002996 { # NOTE: register only one int: with built-in decl
2997 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2998 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2999 }
3000 }
3001 return %TypeAttr;
3002 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003003 else {
3004 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003006 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003007 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
3008 {
3009 %TypeAttr = getTrivialTypeAttr($TypeId);
3010 if($TypeAttr{"Name"})
3011 {
3012 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3013 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3014 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3015 }
3016 return %TypeAttr;
3017 }
3018 else {
3019 return ();
3020 }
3021 }
3022 elsif($TypeAttr{"Type"} eq "SizeOf")
3023 {
3024 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
3025 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
3026 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
3027 if($TypeAttr{"Name"})
3028 {
3029 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3030 return %TypeAttr;
3031 }
3032 else {
3033 return ();
3034 }
3035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003036 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003037 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003038 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3039 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003040 return ();
3041 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003042 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003043 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003044 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003045 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003047 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003048 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 }
3051 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003052 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003053 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003054 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003055 return ();
3056 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003057 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003058 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003059 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003060 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003061 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003062 }
3063 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003064 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065 {
3066 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003067 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003068 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003069 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003070 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3071 }
3072 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003073 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 }
3075 }
3076 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003077 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003078 }
3079 if($TypeAttr{"Type"} eq "Typedef")
3080 {
3081 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003082
3083 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3084 return ();
3085 }
3086
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003087 if(isAnon($TypeAttr{"Name"}))
3088 { # anon typedef to anon type: ._N
3089 return ();
3090 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003091
3092 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3093 { # artificial typedef of "struct X" to "X"
3094 $TypeAttr{"Artificial"} = 1;
3095 }
3096
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 if(my $NS = getNameSpace($TypeDeclId))
3098 {
3099 my $TypeName = $TypeAttr{"Name"};
3100 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3101 { # "some_type" is the typedef to "struct some_type" in C++
3102 if($3) {
3103 $TypeAttr{"Name"} = $3."::".$TypeName;
3104 }
3105 }
3106 else
3107 {
3108 $TypeAttr{"NameSpace"} = $NS;
3109 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003110
3111 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3112 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3113 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003114 if($BTAttr{"NameSpace"}
3115 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003116 { # types like "std::fpos<__mbstate_t>" are
3117 # not covered by typedefs in the TU dump
3118 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003119 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3120 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003121 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003122 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003123 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003124 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003126 }
3127 }
3128 }
3129 }
3130 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003131 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003132 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003133 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003134 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3135 { # typedef int*const TYPEDEF; // first
3136 # int foo(TYPEDEF p); // const is optimized out
3137 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3138 if($BTAttr{"Name"}=~/</)
3139 {
3140 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3141 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003143 }
3144 }
3145 }
3146 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3147 }
3148 if(not $TypeAttr{"Size"})
3149 {
3150 if($TypeAttr{"Type"} eq "Pointer") {
3151 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3152 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003153 elsif($BTAttr{"Size"}) {
3154 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003155 }
3156 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003157 if(my $Algn = getAlgn($TypeId)) {
3158 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3159 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003160 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003161 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3162 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003163 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003164 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003165 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003166 { # typedef to "class Class"
3167 # should not be registered in TName_Tid
3168 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3169 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171 }
3172 return %TypeAttr;
3173 }
3174}
3175
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176sub getTreeVec($)
3177{
3178 my %Vector = ();
3179 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3180 {
3181 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3182 { # string length is N-1 because of the null terminator
3183 $Vector{$1} = $2;
3184 }
3185 }
3186 return \%Vector;
3187}
3188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003189sub get_TemplateParam($$)
3190{
3191 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 return () if(not $Type_Id);
3193 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3194 return () if(not $NodeType);
3195 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003196 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003197 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003198 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003199 my $Num = getNodeIntCst($Type_Id);
3200 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003202 }
3203 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003204 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205 }
3206 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003207 elsif($NodeType eq "string_cst") {
3208 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003210 elsif($NodeType eq "tree_vec")
3211 {
3212 my $Vector = getTreeVec($Type_Id);
3213 my @Params = ();
3214 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3215 {
3216 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3217 push(@Params, $P2);
3218 }
3219 }
3220 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003221 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003222 elsif($NodeType eq "parm_decl")
3223 {
3224 (getNameByInfo($Type_Id));
3225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 else
3227 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003228 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003229 my $PName = $ParamAttr{"Name"};
3230 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003231 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003232 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003233 if($PName=~/\>/)
3234 {
3235 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003236 $PName = $Cover;
3237 }
3238 }
3239 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003240 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3242 # template<typename _Key, typename _Compare = std::less<_Key>
3243 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3244 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3245 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3246 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003247 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003249 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003250 }
3251}
3252
3253sub cover_stdcxx_typedef($)
3254{
3255 my $TypeName = $_[0];
3256 if(my @Covers = sort {length($a)<=>length($b)}
3257 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3258 { # take the shortest typedef
3259 # FIXME: there may be more than
3260 # one typedefs to the same type
3261 return $Covers[0];
3262 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003263 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003264 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3265 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3266 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003267 if(my $Cover = $Covers[0])
3268 {
3269 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3270 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003272 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003273 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274}
3275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003276sub getNodeIntCst($)
3277{
3278 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003279 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003280 if($EnumMembName_Id{$Version}{$CstId}) {
3281 return $EnumMembName_Id{$Version}{$CstId};
3282 }
3283 elsif((my $Value = getTreeValue($CstId)) ne "")
3284 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003285 if($Value eq "0")
3286 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003287 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288 return "false";
3289 }
3290 else {
3291 return "0";
3292 }
3293 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003294 elsif($Value eq "1")
3295 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003296 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003297 return "true";
3298 }
3299 else {
3300 return "1";
3301 }
3302 }
3303 else {
3304 return $Value;
3305 }
3306 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003307 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308}
3309
3310sub getNodeStrCst($)
3311{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003312 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3313 {
3314 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003315 {
3316 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3317 { # string length is N-1 because of the null terminator
3318 return substr($1, 0, $2-1);
3319 }
3320 else
3321 { # identifier_node
3322 return substr($1, 0, $2);
3323 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003324 }
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 Ponomarenko62ddcfa2012-05-23 13:13:15 +04003329sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003330{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003331 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003332 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3333 if($Type eq "FieldPtr") {
3334 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3335 }
3336 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3337 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003338 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003339 if($Type eq "MethodPtr")
3340 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003341 if(my $Size = getSize($TypeId))
3342 {
3343 $Size/=$BYTE_SIZE;
3344 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003346 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003347 if(my $Algn = getAlgn($TypeId)) {
3348 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003350 # Return
3351 if($Type eq "FieldPtr")
3352 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003353 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003354 if($ReturnAttr{"Name"}) {
3355 $MemPtrName .= $ReturnAttr{"Name"};
3356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003357 $TypeAttr{"Return"} = $PtrId;
3358 }
3359 else
3360 {
3361 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3362 {
3363 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003364 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3365 if(not $ReturnAttr{"Name"})
3366 { # templates
3367 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003369 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003370 $TypeAttr{"Return"} = $ReturnTypeId;
3371 }
3372 }
3373 # Class
3374 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3375 {
3376 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003377 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378 if($Class{"Name"}) {
3379 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3380 }
3381 else {
3382 $MemPtrName .= " (*)";
3383 }
3384 }
3385 else {
3386 $MemPtrName .= " (*)";
3387 }
3388 # Parameters
3389 if($Type eq "FuncPtr"
3390 or $Type eq "MethodPtr")
3391 {
3392 my @ParamTypeName = ();
3393 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3394 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003395 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003396 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003397 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003398 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003399 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3400 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003402 my $PTypeId = $1;
3403 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003404 if(not $ParamAttr{"Name"})
3405 { # templates (template_type_parm), etc.
3406 return ();
3407 }
3408 if($ParamAttr{"Name"} eq "void") {
3409 last;
3410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003411 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003412 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003413 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003414 push(@ParamTypeName, $ParamAttr{"Name"});
3415 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003416 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3417 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003418 }
3419 else {
3420 last;
3421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003422 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003423 else {
3424 last;
3425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003426 }
3427 }
3428 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003430 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003431 return %TypeAttr;
3432}
3433
3434sub getTreeTypeName($)
3435{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436 my $TypeId = $_[0];
3437 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003438 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003440 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003441 if(my $Name = getNameByInfo($TypeId))
3442 { # bit_size_type
3443 return $Name;
3444 }
3445 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003446 return "unsigned int";
3447 }
3448 else {
3449 return "int";
3450 }
3451 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003452 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003453 return getNameByInfo($1);
3454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003455 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003456 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003457}
3458
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003459sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003460{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003461 my $Ptd = pointTo($_[0]);
3462 return 0 if(not $Ptd);
3463 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003464 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003465 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3466 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003467 }
3468 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003469 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3470 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003471 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003472 if($InfoT1 eq "pointer_type"
3473 and $InfoT2 eq "function_type") {
3474 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003475 }
3476 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003477 return 0;
3478}
3479
3480sub isMethodPtr($)
3481{
3482 my $Ptd = pointTo($_[0]);
3483 return 0 if(not $Ptd);
3484 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3485 {
3486 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3487 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3488 and $Info=~/ ptrmem /) {
3489 return 1;
3490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003491 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003492 return 0;
3493}
3494
3495sub isFieldPtr($)
3496{
3497 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3498 {
3499 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3500 and $Info=~/ ptrmem /) {
3501 return 1;
3502 }
3503 }
3504 return 0;
3505}
3506
3507sub pointTo($)
3508{
3509 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3510 {
3511 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3512 return $1;
3513 }
3514 }
3515 return "";
3516}
3517
3518sub getTypeTypeByTypeId($)
3519{
3520 my $TypeId = $_[0];
3521 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3522 {
3523 my $NType = $NodeType{$TType};
3524 if($NType eq "Intrinsic") {
3525 return $NType;
3526 }
3527 elsif(isFuncPtr($TypeId)) {
3528 return "FuncPtr";
3529 }
3530 elsif(isMethodPtr($TypeId)) {
3531 return "MethodPtr";
3532 }
3533 elsif(isFieldPtr($TypeId)) {
3534 return "FieldPtr";
3535 }
3536 elsif($NType ne "Other") {
3537 return $NType;
3538 }
3539 }
3540 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541}
3542
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003543my %UnQual = (
3544 "r"=>"restrict",
3545 "v"=>"volatile",
3546 "c"=>"const",
3547 "cv"=>"const volatile"
3548);
3549
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003550sub getQual($)
3551{
3552 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003553 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3554 {
3555 my ($Qual, $To) = ();
3556 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3557 $Qual = $UnQual{$1};
3558 }
3559 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3560 $To = $1;
3561 }
3562 if($Qual and $To) {
3563 return ($Qual, $To);
3564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003565 }
3566 return ();
3567}
3568
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003569sub getQualType($)
3570{
3571 if($_[0] eq "const volatile") {
3572 return "ConstVolatile";
3573 }
3574 return ucfirst($_[0]);
3575}
3576
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003577sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003578{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003579 my $TypeId = $_[0];
3580 my $TypeDeclId = getTypeDeclId($TypeId);
3581 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003582 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003583 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3584 return "Typedef";
3585 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003586 }
3587 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3588 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003589 if(($Qual or $To) and $TypeDeclId
3590 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003591 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003592 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003594 elsif(not $MissedBase_R{$Version}{$TypeId}
3595 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003596 return "Typedef";
3597 }
3598 elsif($Qual)
3599 { # qualified types
3600 return getQualType($Qual);
3601 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003602
3603 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3604 { # typedef struct { ... } name
3605 $TypeTypedef{$Version}{$TypeId} = $1;
3606 }
3607
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003608 my $TypeType = getTypeTypeByTypeId($TypeId);
3609 if($TypeType eq "Struct")
3610 {
3611 if($TypeDeclId
3612 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3613 return "Template";
3614 }
3615 }
3616 return $TypeType;
3617}
3618
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003619sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003620{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003621 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003622 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003623 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3624 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3625 return 0;
3626 }
3627 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3628 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003629 if(my $TDid = getTypeDeclId($_[0]))
3630 {
3631 if(getTypeId($TDid) eq $_[0]
3632 and getNameByInfo($TDid))
3633 {
3634 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3635 return $1;
3636 }
3637 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003638 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003639 }
3640 }
3641 return 0;
3642}
3643
3644sub selectBaseType($)
3645{
3646 my $TypeId = $_[0];
3647 if(defined $MissedTypedef{$Version}{$TypeId})
3648 { # add missed typedefs
3649 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3650 return ($TypeId, "");
3651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003653 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3654 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003655
3656 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3657 my $MB = $MissedBase{$Version}{$TypeId};
3658
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003659 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003660 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003661 and (getTypeId($1) ne $TypeId)
3662 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003663 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003665 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003666 elsif($MB)
3667 { # add base
3668 return ($MB, "");
3669 }
3670 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003671 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003672 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003674 elsif($Qual or $To)
3675 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003677 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003678 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003679 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003680 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003681 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003683 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003684 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003685 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003686 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003687 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003690 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003691 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003692 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003693 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003695 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003696
3697 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003698}
3699
3700sub getSymbolInfo_All()
3701{
3702 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3703 { # reverse order
3704 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003705 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003706 }
3707 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003708
3709 if($ADD_TMPL_INSTANCES)
3710 {
3711 # templates
3712 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3713 {
3714 my %Map = ();
3715
3716 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3717 {
3718 if(defined $TemplateMap{$Version}{$ClassId})
3719 {
3720 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3721 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3722 }
3723 }
3724 }
3725
3726 if(defined $TemplateMap{$Version}{$Sid})
3727 {
3728 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3729 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3730 }
3731 }
3732
3733 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3734 {
3735 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3736 {
3737 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3738 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3739 }
3740 }
3741 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3742 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3743 }
3744 }
3745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003746}
3747
3748sub getVarInfo_All()
3749{
3750 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3751 { # reverse order
3752 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003753 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003754 }
3755 }
3756}
3757
3758sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003759 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003760}
3761
3762sub getVarInfo($)
3763{
3764 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003765 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003766 {
3767 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3768 if($NSInfoType and $NSInfoType eq "function_decl") {
3769 return;
3770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003771 }
3772 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3773 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3774 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3775 delete($SymbolInfo{$Version}{$InfoId});
3776 return;
3777 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003778 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003779 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003780 delete($SymbolInfo{$Version}{$InfoId});
3781 return;
3782 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003783 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3784 delete($SymbolInfo{$Version}{$InfoId});
3785 return;
3786 }
3787 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003788 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3789 {
3790 if($OSgroup eq "windows")
3791 { # cut the offset
3792 $MnglName=~s/\@\d+\Z//g;
3793 }
3794 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003796 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003797 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003798 { # validate mangled name
3799 delete($SymbolInfo{$Version}{$InfoId});
3800 return;
3801 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003802 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003803 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003804 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003805 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003806 }
3807 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3808 { # non-public global data
3809 delete($SymbolInfo{$Version}{$InfoId});
3810 return;
3811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003813 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003814 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003815 if(not defined $TypeInfo{$Version}{$Rid}
3816 or not $TypeInfo{$Version}{$Rid}{"Name"})
3817 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003818 delete($SymbolInfo{$Version}{$InfoId});
3819 return;
3820 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003821 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3822 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003823 if(defined $Val) {
3824 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003826 }
3827 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003828 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3829 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003830 if(not defined $TypeInfo{$Version}{$ClassId}
3831 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3832 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003833 delete($SymbolInfo{$Version}{$InfoId});
3834 return;
3835 }
3836 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003837 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3838 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003839 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003840 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003841 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003842 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003843 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003844 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003845 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003846 if(not $CheckHeadersOnly)
3847 {
3848 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3849 {
3850 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3851 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3852 {
3853 if(link_symbol($ShortName, $Version, "-Deps"))
3854 { # "const" global data is mangled as _ZL... in the TU dump
3855 # but not mangled when compiling a C shared library
3856 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3857 }
3858 }
3859 }
3860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003861 if($COMMON_LANGUAGE{$Version} eq "C++")
3862 {
3863 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3864 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003865 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003866 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3867 }
3868 }
3869 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3870 { # try to mangle symbol (link with libraries)
3871 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3872 }
3873 if($OStarget eq "windows")
3874 {
3875 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3876 { # link MS C++ symbols from library with GCC symbols from headers
3877 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3878 }
3879 }
3880 }
3881 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3882 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3883 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003884 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3885 {
3886 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3887 { # non-target symbols
3888 delete($SymbolInfo{$Version}{$InfoId});
3889 return;
3890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003891 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003892 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3893 {
3894 if(defined $MissedTypedef{$Version}{$Rid})
3895 {
3896 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3897 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3898 }
3899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003900 }
3901 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003902 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003903 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3904 }
3905 if($ShortName=~/\A(_Z|\?)/) {
3906 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3907 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003908
3909 if($ExtraDump) {
3910 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003912}
3913
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003914sub isConstType($$)
3915{
3916 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003917 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003918 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003919 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003920 }
3921 return ($Base{"Type"} eq "Const");
3922}
3923
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003924sub getTrivialName($$)
3925{
3926 my ($TypeInfoId, $TypeId) = @_;
3927 my %TypeAttr = ();
3928 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3929 if(not $TypeAttr{"Name"}) {
3930 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3931 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003932 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003933 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003934 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003935 if(isAnon($TypeAttr{"Name"}))
3936 {
3937 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003938 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003939 { # searching for a first not anon scope
3940 if($NSId eq $NameSpaceId) {
3941 last;
3942 }
3943 else
3944 {
3945 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3946 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003947 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003948 last;
3949 }
3950 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003951 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003952 }
3953 }
3954 else
3955 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003956 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003957 {
3958 if($NameSpaceId ne $TypeId) {
3959 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003961 }
3962 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003963 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003964 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3965 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003966 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003967 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003968 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003969 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003971 if($TypeAttr{"NameSpace"}) {
3972 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003974 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003975 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3976 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003977 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003978 if(my @TParams = getTParams($TypeId, "Type")) {
3979 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3980 }
3981 else {
3982 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003984 }
3985 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3986}
3987
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003988sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003989{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003990 my $TypeId = $_[0];
3991 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003992
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003993 my %TypeAttr = ();
3994
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003995 if($TemplateDecl{$Version}{$TypeId})
3996 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003997 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003998 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004000 setTypeAccess($TypeId, \%TypeAttr);
4001 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
4002 if(isBuiltIn($TypeAttr{"Header"}))
4003 {
4004 delete($TypeAttr{"Header"});
4005 delete($TypeAttr{"Line"});
4006 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004007
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004008 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004009 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
4010 if(not $TypeAttr{"Name"}) {
4011 return ();
4012 }
4013 if(not $TypeAttr{"NameSpace"}) {
4014 delete($TypeAttr{"NameSpace"});
4015 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004016
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004017 if($TypeAttr{"Type"} eq "Intrinsic")
4018 {
4019 if(defined $TypeAttr{"Header"})
4020 {
4021 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
4022 { # support for SUSE 11.2
4023 # integer_type has srcp dump{1-2}.i
4024 delete($TypeAttr{"Header"});
4025 }
4026 }
4027 }
4028
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004029 my $Tmpl = undef;
4030
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004031 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004032 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004033 $Tmpl = $BasicTemplate{$Version}{$TypeId};
4034
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004035 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004036 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004037 foreach my $Pos (0 .. $#TParams)
4038 {
4039 my $Val = $TParams[$Pos];
4040 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4041
4042 if(not defined $TypeAttr{"Template"})
4043 {
4044 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4045
4046 if($Base{"Type"} eq "TemplateParam"
4047 or defined $Base{"Template"}) {
4048 $TypeAttr{"Template"} = 1;
4049 }
4050 }
4051
4052 if($Tmpl)
4053 {
4054 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4055 {
4056 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4057
4058 if($Val eq $Arg) {
4059 $TypeAttr{"Template"} = 1;
4060 }
4061 }
4062 }
4063 }
4064
4065 if($Tmpl)
4066 {
4067 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4068 {
4069 if($Pos>$#TParams)
4070 {
4071 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4072 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4073 }
4074 }
4075 }
4076 }
4077
4078 if($ADD_TMPL_INSTANCES)
4079 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004080 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004081 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004082 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004083 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004084 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004085 {
4086 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4087 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4088 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004089 }
4090 if(not getTreeAttr_Binf($TypeId))
4091 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004092 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4093 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4094 }
4095 }
4096 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004097 }
4098 }
4099 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004100
4101 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4102
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004103 if(my $Size = getSize($TypeId))
4104 {
4105 $Size = $Size/$BYTE_SIZE;
4106 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004107 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004108 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004109 {
4110 if($ExtraDump)
4111 {
4112 if(not defined $TypeAttr{"Memb"}
4113 and not $Tmpl)
4114 { # declaration only
4115 $TypeAttr{"Forward"} = 1;
4116 }
4117 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004118 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004119
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004120 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004121 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004122 {
4123 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004124 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 }
4126 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004127 or $TypeAttr{"Type"} eq "Class")
4128 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004129 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004130 if($Skip) {
4131 return ();
4132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004133 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004134 if(my $Algn = getAlgn($TypeId)) {
4135 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004138
4139 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4140 {
4141 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004142 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004143 {
4144 if(not isAnon($TypeAttr{"Name"})) {
4145 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4146 }
4147 }
4148 }
4149
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004150 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004151 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4152 {
4153 my @Entries = split(/\n/, $VTable);
4154 foreach (1 .. $#Entries)
4155 {
4156 my $Entry = $Entries[$_];
4157 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004158 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 }
4160 }
4161 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004162
4163 if($TypeAttr{"Type"} eq "Enum")
4164 {
4165 if(not $TypeAttr{"NameSpace"})
4166 {
4167 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4168 {
4169 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004170 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004171 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004172 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004173 "Header"=>$TypeAttr{"Header"}
4174 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004175 if(isAnon($TypeAttr{"Name"}))
4176 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004177 if($ExtraDump
4178 or is_target_header($TypeAttr{"Header"}, $Version))
4179 {
4180 %{$Constants{$Version}{$MName}} = (
4181 "Value" => $MVal,
4182 "Header" => $TypeAttr{"Header"}
4183 );
4184 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004185 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004186 }
4187 }
4188 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004189 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004190 {
4191 if(defined $TypedefToAnon{$TypeId}) {
4192 $TypeAttr{"AnonTypedef"} = 1;
4193 }
4194 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004196 return %TypeAttr;
4197}
4198
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004199sub simplifyVTable($)
4200{
4201 my $Content = $_[0];
4202 if($Content=~s/ \[with (.+)]//)
4203 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4204 if(my @Elems = separate_Params($1, 0, 0))
4205 {
4206 foreach my $Elem (@Elems)
4207 {
4208 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4209 {
4210 my ($Arg, $Val) = ($1, $2);
4211
4212 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4213 $Content=~s/,\s*$Arg\b//g;
4214 }
4215 else {
4216 $Content=~s/\b$Arg\b/$Val/g;
4217 }
4218 }
4219 }
4220 }
4221 }
4222
4223 return $Content;
4224}
4225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004226sub detect_lang($)
4227{
4228 my $TypeId = $_[0];
4229 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004230 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004231 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004232 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4233 }
4234 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004235 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004236 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004237 while($Fncs)
4238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004239 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004240 return 1;
4241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004242 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004243 }
4244 }
4245 return 0;
4246}
4247
4248sub setSpec($$)
4249{
4250 my ($TypeId, $TypeAttr) = @_;
4251 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4252 if($Info=~/\s+spec\s+/) {
4253 $TypeAttr->{"Spec"} = 1;
4254 }
4255}
4256
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004257sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004258{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004259 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004260 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004261 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004262 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004263 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004264 my $Pos = 0;
4265 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4266 {
4267 my ($Access, $BInfoId) = ($1, $2);
4268 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004269
4270 if($ClassId==$TypeId)
4271 { # class A<N>:public A<N-1>
4272 next;
4273 }
4274
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004275 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4276 if(not $CType or $CType eq "template_type_parm"
4277 or $CType eq "typename_type")
4278 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004279 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004281 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004282 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004283 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4284 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004285 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004286 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4287 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004288 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004289 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004290 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004291 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4292 }
4293 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004294 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004295 }
4296 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004297 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004298}
4299
4300sub getBinfClassId($)
4301{
4302 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4303 $Info=~/type[ ]*:[ ]*@(\d+) /;
4304 return $1;
4305}
4306
4307sub unmangledFormat($$)
4308{
4309 my ($Name, $LibVersion) = @_;
4310 $Name = uncover_typedefs($Name, $LibVersion);
4311 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4312 $Name=~s/\(\w+\)(\d)/$1/;
4313 return $Name;
4314}
4315
4316sub modelUnmangled($$)
4317{
4318 my ($InfoId, $Compiler) = @_;
4319 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4320 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4321 }
4322 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4323 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4324 $PureSignature = "~".$PureSignature;
4325 }
4326 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4327 {
4328 my (@Params, @ParamTypes) = ();
4329 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4330 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4331 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4332 }
4333 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4334 { # checking parameters
4335 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004336 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004337 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004338 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004339
4340 if($PName eq "this"
4341 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4342 {
4343 next;
4344 }
4345
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004346 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004347 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004348 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004349 }
4350 @ParamTypes = (@ParamTypes, $PTName);
4351 }
4352 if(@ParamTypes) {
4353 $PureSignature .= "(".join(", ", @ParamTypes).")";
4354 }
4355 else
4356 {
4357 if($Compiler eq "MSVC")
4358 {
4359 $PureSignature .= "(void)";
4360 }
4361 else
4362 { # GCC
4363 $PureSignature .= "()";
4364 }
4365 }
4366 $PureSignature = delete_keywords($PureSignature);
4367 }
4368 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4369 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004370 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004371 $PureSignature = $ClassName."::".$PureSignature;
4372 }
4373 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4374 $PureSignature = $NS."::".$PureSignature;
4375 }
4376 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4377 $PureSignature .= " const";
4378 }
4379 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4380 $PureSignature .= " volatile";
4381 }
4382 my $ShowReturn = 0;
4383 if($Compiler eq "MSVC"
4384 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4385 {
4386 $ShowReturn=1;
4387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004388 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4389 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004390 {
4391 $ShowReturn=1;
4392 }
4393 if($ShowReturn)
4394 { # mangled names for template function specializations include return value
4395 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4396 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004397 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004398 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4399 $PureSignature = $ReturnName." ".$PureSignature;
4400 }
4401 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004402 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004403}
4404
4405sub mangle_symbol($$$)
4406{ # mangling for simple methods
4407 # see gcc-4.6.0/gcc/cp/mangle.c
4408 my ($InfoId, $LibVersion, $Compiler) = @_;
4409 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4410 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4411 }
4412 my $Mangled = "";
4413 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004414 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004415 }
4416 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004417 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004418 }
4419 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4420}
4421
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004422sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004423{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004424 my ($InfoId, $LibVersion) = @_;
4425 return "";
4426}
4427
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004428sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004429{ # see gcc-4.6.0/gcc/cp/mangle.c
4430 my ($InfoId, $LibVersion) = @_;
4431 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004432 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433 my %Repl = ();# SN_ replacements
4434 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4435 {
4436 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4437 if($MangledClass!~/\AN/) {
4438 $MangledClass = "N".$MangledClass;
4439 }
4440 else {
4441 $MangledClass=~s/E\Z//;
4442 }
4443 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4444 $MangledClass=~s/\AN/NV/;
4445 }
4446 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4447 $MangledClass=~s/\AN/NK/;
4448 }
4449 $Mangled .= $MangledClass;
4450 }
4451 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4452 { # mangled by name due to the absence of structured info
4453 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4454 if($MangledNS!~/\AN/) {
4455 $MangledNS = "N".$MangledNS;
4456 }
4457 else {
4458 $MangledNS=~s/E\Z//;
4459 }
4460 $Mangled .= $MangledNS;
4461 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004462 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004463 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004464 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004465 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004466 foreach (@TPos) {
4467 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4468 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004469 }
4470 elsif($TmplParams)
4471 { # remangling mode
4472 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004473 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004474 }
4475 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4476 $Mangled .= "C1";
4477 }
4478 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4479 $Mangled .= "D0";
4480 }
4481 elsif($ShortName)
4482 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004483 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4484 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004485 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004486 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004487 { # "const" global data is mangled as _ZL...
4488 $Mangled .= "L";
4489 }
4490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004491 if($ShortName=~/\Aoperator(\W.*)\Z/)
4492 {
4493 my $Op = $1;
4494 $Op=~s/\A[ ]+//g;
4495 if(my $OpMngl = $OperatorMangling{$Op}) {
4496 $Mangled .= $OpMngl;
4497 }
4498 else { # conversion operator
4499 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4500 }
4501 }
4502 else {
4503 $Mangled .= length($ShortName).$ShortName;
4504 }
4505 if(@TParams)
4506 { # templates
4507 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004508 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004509 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4510 }
4511 $Mangled .= "E";
4512 }
4513 if(not $ClassId and @TParams) {
4514 add_substitution($ShortName, \%Repl, 0);
4515 }
4516 }
4517 if($ClassId or $NameSpace) {
4518 $Mangled .= "E";
4519 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004520 if(@TParams)
4521 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004522 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004523 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4524 }
4525 }
4526 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4527 {
4528 my @Params = ();
4529 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4530 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4531 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4532 }
4533 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4534 { # checking parameters
4535 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4536 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4537 }
4538 if(not @Params) {
4539 $Mangled .= "v";
4540 }
4541 }
4542 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4543 $Mangled = write_stdcxx_substitution($Mangled);
4544 if($Mangled eq "_Z") {
4545 return "";
4546 }
4547 return $Mangled;
4548}
4549
4550sub correct_incharge($$$)
4551{
4552 my ($InfoId, $LibVersion, $Mangled) = @_;
4553 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4554 {
4555 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004556 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004557 }
4558 }
4559 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4560 {
4561 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004562 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004563 }
4564 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004565 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004566 }
4567 }
4568 return $Mangled;
4569}
4570
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004571sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004572{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004573 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004574 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004575 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004576 return $Name;
4577 }
4578 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004579 while(my $CPos = find_center($TParams, "<"))
4580 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581 $TParams = substr($TParams, $CPos);
4582 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004583 if($TParams=~s/\A<(.+)>\Z/$1/) {
4584 $Name=~s/<\Q$TParams\E>\Z//;
4585 }
4586 else
4587 { # error
4588 $TParams = "";
4589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004590 return ($Name, $TParams);
4591}
4592
4593sub get_sub_ns($)
4594{
4595 my $Name = $_[0];
4596 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004597 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004598 {
4599 push(@NS, substr($Name, 0, $CPos));
4600 $Name = substr($Name, $CPos);
4601 $Name=~s/\A:://;
4602 }
4603 return (join("::", @NS), $Name);
4604}
4605
4606sub mangle_ns($$$)
4607{
4608 my ($Name, $LibVersion, $Repl) = @_;
4609 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4610 {
4611 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4612 $Mangled=~s/\AN(.+)E\Z/$1/;
4613 return $Mangled;
4614
4615 }
4616 else
4617 {
4618 my ($MangledNS, $SubNS) = ("", "");
4619 ($SubNS, $Name) = get_sub_ns($Name);
4620 if($SubNS) {
4621 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4622 }
4623 $MangledNS .= length($Name).$Name;
4624 add_substitution($MangledNS, $Repl, 0);
4625 return $MangledNS;
4626 }
4627}
4628
4629sub mangle_param($$$)
4630{
4631 my ($PTid, $LibVersion, $Repl) = @_;
4632 my ($MPrefix, $Mangled) = ("", "");
4633 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004634 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004635 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004636 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004637 if(not $BaseType_Name) {
4638 return "";
4639 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004640 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004641 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004642 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4643 while($Suffix=~/(&|\*|const)\Z/)
4644 {
4645 if($Suffix=~s/[ ]*&\Z//) {
4646 $MPrefix .= "R";
4647 }
4648 if($Suffix=~s/[ ]*\*\Z//) {
4649 $MPrefix .= "P";
4650 }
4651 if($Suffix=~s/[ ]*const\Z//)
4652 {
4653 if($MPrefix=~/R|P/
4654 or $Suffix=~/&|\*/) {
4655 $MPrefix .= "K";
4656 }
4657 }
4658 if($Suffix=~s/[ ]*volatile\Z//) {
4659 $MPrefix .= "V";
4660 }
4661 #if($Suffix=~s/[ ]*restrict\Z//) {
4662 #$MPrefix .= "r";
4663 #}
4664 }
4665 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4666 $Mangled .= $Token;
4667 }
4668 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4669 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004670 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004671 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004672 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004673 foreach (@TPos) {
4674 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4675 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004676 }
4677 elsif($TmplParams)
4678 { # remangling mode
4679 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004680 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004681 }
4682 my $MangledNS = "";
4683 my ($SubNS, $SName) = get_sub_ns($ShortName);
4684 if($SubNS) {
4685 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4686 }
4687 $MangledNS .= length($SName).$SName;
4688 if(@TParams) {
4689 add_substitution($MangledNS, $Repl, 0);
4690 }
4691 $Mangled .= "N".$MangledNS;
4692 if(@TParams)
4693 { # templates
4694 $Mangled .= "I";
4695 foreach my $TParam (@TParams) {
4696 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4697 }
4698 $Mangled .= "E";
4699 }
4700 $Mangled .= "E";
4701 }
4702 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4703 {
4704 if($BaseType{"Type"} eq "MethodPtr") {
4705 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4706 }
4707 else {
4708 $Mangled .= "PF";
4709 }
4710 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4711 my @Params = keys(%{$BaseType{"Param"}});
4712 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4713 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4714 }
4715 if(not @Params) {
4716 $Mangled .= "v";
4717 }
4718 $Mangled .= "E";
4719 }
4720 elsif($BaseType{"Type"} eq "FieldPtr")
4721 {
4722 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4723 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4724 }
4725 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4726 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4727 {
4728 if($Mangled eq $Optimized)
4729 {
4730 if($ShortName!~/::/)
4731 { # remove "N ... E"
4732 if($MPrefix) {
4733 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4734 }
4735 else {
4736 $Mangled=~s/\AN(.+)E\Z/$1/g;
4737 }
4738 }
4739 }
4740 else {
4741 $Mangled = $Optimized;
4742 }
4743 }
4744 add_substitution($Mangled, $Repl, 1);
4745 return $Mangled;
4746}
4747
4748sub mangle_template_param($$$)
4749{ # types + literals
4750 my ($TParam, $LibVersion, $Repl) = @_;
4751 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4752 return mangle_param($TPTid, $LibVersion, $Repl);
4753 }
4754 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4755 { # class_name<1u>::method(...)
4756 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4757 }
4758 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4759 { # class_name<(signed char)1>::method(...)
4760 return "L".$IntrinsicMangling{$1}.$2."E";
4761 }
4762 elsif($TParam eq "true")
4763 { # class_name<true>::method(...)
4764 return "Lb1E";
4765 }
4766 elsif($TParam eq "false")
4767 { # class_name<true>::method(...)
4768 return "Lb0E";
4769 }
4770 else { # internal error
4771 return length($TParam).$TParam;
4772 }
4773}
4774
4775sub add_substitution($$$)
4776{
4777 my ($Value, $Repl, $Rec) = @_;
4778 if($Rec)
4779 { # subtypes
4780 my @Subs = ($Value);
4781 while($Value=~s/\A(R|P|K)//) {
4782 push(@Subs, $Value);
4783 }
4784 foreach (reverse(@Subs)) {
4785 add_substitution($_, $Repl, 0);
4786 }
4787 return;
4788 }
4789 return if($Value=~/\AS(\d*)_\Z/);
4790 $Value=~s/\AN(.+)E\Z/$1/g;
4791 return if(defined $Repl->{$Value});
4792 return if(length($Value)<=1);
4793 return if($StdcxxMangling{$Value});
4794 # check for duplicates
4795 my $Base = $Value;
4796 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4797 {
4798 my $Num = $Repl->{$Type};
4799 my $Replace = macro_mangle($Num);
4800 $Base=~s/\Q$Replace\E/$Type/;
4801 }
4802 if(my $OldNum = $Repl->{$Base})
4803 {
4804 $Repl->{$Value} = $OldNum;
4805 return;
4806 }
4807 my @Repls = sort {$b<=>$a} values(%{$Repl});
4808 if(@Repls) {
4809 $Repl->{$Value} = $Repls[0]+1;
4810 }
4811 else {
4812 $Repl->{$Value} = -1;
4813 }
4814 # register duplicates
4815 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004816 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004817 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4818 {
4819 next if($Base eq $Type);
4820 my $Num = $Repl->{$Type};
4821 my $Replace = macro_mangle($Num);
4822 $Base=~s/\Q$Type\E/$Replace/;
4823 $Repl->{$Base} = $Repl->{$Value};
4824 }
4825}
4826
4827sub macro_mangle($)
4828{
4829 my $Num = $_[0];
4830 if($Num==-1) {
4831 return "S_";
4832 }
4833 else
4834 {
4835 my $Code = "";
4836 if($Num<10)
4837 { # S0_, S1_, S2_, ...
4838 $Code = $Num;
4839 }
4840 elsif($Num>=10 and $Num<=35)
4841 { # SA_, SB_, SC_, ...
4842 $Code = chr(55+$Num);
4843 }
4844 else
4845 { # S10_, S11_, S12_
4846 $Code = $Num-26; # 26 is length of english alphabet
4847 }
4848 return "S".$Code."_";
4849 }
4850}
4851
4852sub write_stdcxx_substitution($)
4853{
4854 my $Mangled = $_[0];
4855 if($StdcxxMangling{$Mangled}) {
4856 return $StdcxxMangling{$Mangled};
4857 }
4858 else
4859 {
4860 my @Repls = keys(%StdcxxMangling);
4861 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4862 foreach my $MangledType (@Repls)
4863 {
4864 my $Replace = $StdcxxMangling{$MangledType};
4865 #if($Mangled!~/$Replace/) {
4866 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4867 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4868 #}
4869 }
4870 }
4871 return $Mangled;
4872}
4873
4874sub write_substitution($$)
4875{
4876 my ($Mangled, $Repl) = @_;
4877 if(defined $Repl->{$Mangled}
4878 and my $MnglNum = $Repl->{$Mangled}) {
4879 $Mangled = macro_mangle($MnglNum);
4880 }
4881 else
4882 {
4883 my @Repls = keys(%{$Repl});
4884 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4885 # FIXME: how to apply replacements? by num or by pos
4886 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4887 foreach my $MangledType (@Repls)
4888 {
4889 my $Replace = macro_mangle($Repl->{$MangledType});
4890 if($Mangled!~/$Replace/) {
4891 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4892 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4893 }
4894 }
4895 }
4896 return $Mangled;
4897}
4898
4899sub delete_keywords($)
4900{
4901 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004902 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004903 return $TypeName;
4904}
4905
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004906sub uncover_typedefs($$)
4907{
4908 my ($TypeName, $LibVersion) = @_;
4909 return "" if(not $TypeName);
4910 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4911 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4912 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004913 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004914 while($TypeName_New ne $TypeName_Pre)
4915 {
4916 $TypeName_Pre = $TypeName_New;
4917 my $TypeName_Copy = $TypeName_New;
4918 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004919 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004920 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004921 if(not $Intrinsic_Keywords{$1}) {
4922 $Words{$1} = 1;
4923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004924 }
4925 foreach my $Word (keys(%Words))
4926 {
4927 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4928 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004929 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930 if($BaseType_Name=~/\([\*]+\)/)
4931 { # FuncPtr
4932 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4933 {
4934 my $Type_Suffix = $1;
4935 $TypeName_New = $BaseType_Name;
4936 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004937 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004938 }
4939 }
4940 }
4941 else
4942 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004943 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004944 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004945 }
4946 }
4947 }
4948 }
4949 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4950}
4951
4952sub isInternal($)
4953{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004954 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4955 {
4956 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4957 {
4958 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4959 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4960 return 1;
4961 }
4962 }
4963 }
4964 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004965}
4966
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004967sub getDataVal($$)
4968{
4969 my ($InfoId, $TypeId) = @_;
4970 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4971 {
4972 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4973 {
4974 if(defined $LibInfo{$Version}{"info_type"}{$1}
4975 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004976 {
4977 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004978 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004979 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4980 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004981 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004982 if(my $Addr = getTreeAttr_Op($1)) {
4983 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004984 }
4985 }
4986 }
4987 }
4988 else {
4989 return getInitVal($1, $TypeId);
4990 }
4991 }
4992 }
4993 return undef;
4994}
4995
4996sub getInitVal($$)
4997{
4998 my ($InfoId, $TypeId) = @_;
4999 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
5000 {
5001 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
5002 {
5003 if($InfoType eq "integer_cst")
5004 {
5005 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005006 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005007 { # characters
5008 $Val = chr($Val);
5009 }
5010 return $Val;
5011 }
5012 elsif($InfoType eq "string_cst") {
5013 return getNodeStrCst($InfoId);
5014 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005015 elsif($InfoType eq "var_decl")
5016 {
5017 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
5018 return $Name;
5019 }
5020 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005021 }
5022 }
5023 return undef;
5024}
5025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005026sub set_Class_And_Namespace($)
5027{
5028 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005029 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005030 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005031 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005032 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005033 my $NSInfoId = $1;
5034 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
5035 {
5036 if($InfoType eq "namespace_decl") {
5037 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
5038 }
5039 elsif($InfoType eq "record_type") {
5040 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
5041 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005043 }
5044 }
5045 if($SymbolInfo{$Version}{$InfoId}{"Class"}
5046 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005047 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005048 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005049 { # skip
5050 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005052 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005053
5054 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005055}
5056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005057sub debugMangling($)
5058{
5059 my $LibVersion = $_[0];
5060 my %Mangled = ();
5061 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5062 {
5063 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5064 {
5065 if($Mngl=~/\A(_Z|\?)/) {
5066 $Mangled{$Mngl}=$InfoId;
5067 }
5068 }
5069 }
5070 translateSymbols(keys(%Mangled), $LibVersion);
5071 foreach my $Mngl (keys(%Mangled))
5072 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005073 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5074 my $U2 = $tr_name{$Mngl};
5075 if($U1 ne $U2) {
5076 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005077 }
5078 }
5079}
5080
5081sub linkSymbol($)
5082{ # link symbols from shared libraries
5083 # with the symbols from header files
5084 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005086 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005087 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5088 or $EMERGENCY_MODE_48)
5089 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5090 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
5091 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005092 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005093 {
5094 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5095 return correct_incharge($InfoId, $Version, $Mangled);
5096 }
5097 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005098 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005099 or not $BinaryOnly
5100 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005101 { # 1. --headers-only mode
5102 # 2. not mangled src-only symbols
5103 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5104 return $Mangled;
5105 }
5106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005107 }
5108 return "";
5109}
5110
5111sub setLanguage($$)
5112{
5113 my ($LibVersion, $Lang) = @_;
5114 if(not $UserLang) {
5115 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5116 }
5117}
5118
5119sub getSymbolInfo($)
5120{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005122 if(isInternal($InfoId)) {
5123 return;
5124 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005125 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5126 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005127 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5128 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005129 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005130 return;
5131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 setFuncAccess($InfoId);
5133 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005134 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5135 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005136 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005137 return;
5138 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005139
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005140 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005141 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005142 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005143 if(not defined $TypeInfo{$Version}{$Return}
5144 or not $TypeInfo{$Version}{$Return}{"Name"})
5145 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005146 delete($SymbolInfo{$Version}{$InfoId});
5147 return;
5148 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005149 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005150 }
5151 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5152 {
5153 if(defined $MissedTypedef{$Version}{$Rid})
5154 {
5155 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5156 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5157 }
5158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005159 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005160 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5161 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005162 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005163 my $Orig = getFuncOrig($InfoId);
5164 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005165 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5166 {
5167 delete($SymbolInfo{$Version}{$InfoId});
5168 return;
5169 }
5170
5171 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005172 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005173 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 return;
5175 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005176
5177 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005178 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005179 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5180
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005181 my @TParams = getTParams($Orig, "Func");
5182 if(not @TParams)
5183 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005184 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185 return;
5186 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005187 foreach my $Pos (0 .. $#TParams)
5188 {
5189 my $Val = $TParams[$Pos];
5190 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5191
5192 if($Tmpl)
5193 {
5194 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5195 {
5196 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5197 }
5198 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005199 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005200
5201 if($Tmpl)
5202 {
5203 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5204 {
5205 if($Pos>$#TParams)
5206 {
5207 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5208 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5209 }
5210 }
5211 }
5212
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005213 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5214 { # operator<< <T>, operator>> <T>
5215 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5216 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005217 if(@TParams) {
5218 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5219 }
5220 else {
5221 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5222 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005223 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005224 }
5225 else
5226 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005227 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005229 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5230 {
5231 if($OSgroup eq "windows")
5232 { # cut the offset
5233 $MnglName=~s/\@\d+\Z//g;
5234 }
5235 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5236
5237 # NOTE: mangling of some symbols may change depending on GCC version
5238 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5239 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5240 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005241
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005242 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005243 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 return;
5247 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005250 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005251 if($Skip)
5252 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005253 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 return;
5255 }
5256 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005257 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5258 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5259 }
5260
5261 if(set_Class_And_Namespace($InfoId))
5262 {
5263 delete($SymbolInfo{$Version}{$InfoId});
5264 return;
5265 }
5266
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005267 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5268 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005269 if(not defined $TypeInfo{$Version}{$ClassId}
5270 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005272 delete($SymbolInfo{$Version}{$InfoId});
5273 return;
5274 }
5275 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005276 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5277 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005278 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005279 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005281 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005282 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005283 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005284 }
5285 if($COMMON_LANGUAGE{$Version} eq "C++")
5286 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005287 # C++ or --headers-only mode
5288 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005289 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005290 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5291 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005292 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005293 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005295 if(my $Mangled = linkSymbol($InfoId)) {
5296 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005297 }
5298 }
5299 if($OStarget eq "windows")
5300 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005301 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005303 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005305 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005306 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005307 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005308 }
5309 }
5310 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005311 else
5312 { # not mangled in C
5313 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5314 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005315 if(not $CheckHeadersOnly
5316 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5317 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5318 {
5319 my $Incorrect = 0;
5320
5321 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5322 {
5323 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5324 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5325 { # mangled in the TU dump, but not mangled in the library
5326 $Incorrect = 1;
5327 }
5328 }
5329 else
5330 {
5331 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5332 { # all C++ functions are not mangled in the TU dump
5333 $Incorrect = 1;
5334 }
5335 }
5336 if($Incorrect)
5337 {
5338 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5339 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5340 }
5341 }
5342 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005343 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005344 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005345 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005346 return;
5347 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005348 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005349 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005350 { # identify virtual and pure virtual functions
5351 # NOTE: constructors cannot be virtual
5352 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5353 # in the TU dump, so taking it from the original symbol
5354 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5355 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5356 { # NOTE: D2 destructors are not present in a v-table
5357 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005360 if(isInline($InfoId)) {
5361 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005363 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005364 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5365 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005366 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5367 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005368 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005369 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005370 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005371 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005372 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005373 }
5374 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005375 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5376 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005377 if(not $ExtraDump)
5378 {
5379 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5380 { # non-target symbols
5381 delete($SymbolInfo{$Version}{$InfoId});
5382 return;
5383 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005385 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005386 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5387 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5388 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5389 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005391 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5392 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005393 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 return;
5395 }
5396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005397 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005398 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005399 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005400 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005401 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 return;
5403 }
5404 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005405 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005406 }
5407 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005408 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5409 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5410 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005411 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005412 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5413 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005415 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005417 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005418 }
5419 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005420 if(getFuncLink($InfoId) eq "Static") {
5421 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005422 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005423 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5424 {
5425 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5426 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005427 if($Unmangled=~/\.\_\d/)
5428 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005429 delete($SymbolInfo{$Version}{$InfoId});
5430 return;
5431 }
5432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005433 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005434
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005435 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5436 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005437 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005438 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5439 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005440 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005441
5442 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5443 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5444 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005445
5446 if($ExtraDump) {
5447 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5448 }
5449}
5450
5451sub guessHeader($)
5452{
5453 my $InfoId = $_[0];
5454 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5455 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5456 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5457 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5458 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5459 {
5460 if(get_filename($HPath) eq $Header)
5461 {
5462 my $HDir = get_filename(get_dirname($HPath));
5463 if($HDir ne "include"
5464 and $HDir=~/\A[a-z]+\Z/i) {
5465 return join_P($HDir, $Header);
5466 }
5467 }
5468 }
5469 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470}
5471
5472sub isInline($)
5473{ # "body: undefined" in the tree
5474 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005475 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5476 {
5477 if($Info=~/ undefined /i) {
5478 return 0;
5479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 }
5481 return 1;
5482}
5483
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005484sub hasThrow($)
5485{
5486 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5487 {
5488 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5489 return getTreeAttr_Unql($1, "unql");
5490 }
5491 }
5492 return 1;
5493}
5494
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495sub getTypeId($)
5496{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005497 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5498 {
5499 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5500 return $1;
5501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005503 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504}
5505
5506sub setTypeMemb($$)
5507{
5508 my ($TypeId, $TypeAttr) = @_;
5509 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005510 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005511 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 if($TypeType eq "Enum")
5513 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005514 my $MInfoId = getTreeAttr_Csts($TypeId);
5515 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005516 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005517 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5518 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005519 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005520 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5521 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005522 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005523 }
5524 }
5525 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5526 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005527 my $MInfoId = getTreeAttr_Flds($TypeId);
5528 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005529 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005530 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5531 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005532 if(not $IType or $IType ne "field_decl")
5533 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005534
5535 if($IType eq "var_decl")
5536 { # static field
5537 $StaticFields = 1;
5538 }
5539
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005540 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541 next;
5542 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005543 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005544 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005545 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005546 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 }
5548 if(not $StructMembName)
5549 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005550 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005552 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5554 if(isAnon($UnnamedTName))
5555 { # rename unnamed fields to unnamed0, unnamed1, ...
5556 $StructMembName = "unnamed".($UnnamedPos++);
5557 }
5558 }
5559 }
5560 if(not $StructMembName)
5561 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005562 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 next;
5564 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005565 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005566 if(defined $MissedTypedef{$Version}{$MembTypeId})
5567 {
5568 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5569 $MembTypeId = $AddedTid;
5570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005572
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005573 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5574 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005575 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005576 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005577 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5578 }
5579 if($MInfo=~/spec:\s*mutable /)
5580 { # mutable fields
5581 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005582 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005583 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005584 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5585 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005586 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005587 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005588 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005589 }
5590 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005591 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005592 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5593 { # template
5594 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5595 }
5596 else {
5597 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005600
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005601 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005602 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005603 }
5604 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005605
5606 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005607}
5608
5609sub setFuncParams($)
5610{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005611 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005612 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005613
5614 my $FType = getFuncType($InfoId);
5615
5616 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005617 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005618 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5619 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005620 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005621 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005622 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5623 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005624 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005625 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005627 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005628 else
5629 { # skip
5630 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005631 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005632 # skip "this"-parameter
5633 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005634 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005635 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005636 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005637 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005638 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5639 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5640 if(not $ParamName)
5641 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005642 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005643 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005644 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5645 {
5646 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5647 $ParamTypeId = $AddedTid;
5648 }
5649 }
5650 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005651 if(not $PType or $PType eq "Unknown") {
5652 return 1;
5653 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005654 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005655 if(not $PTName) {
5656 return 1;
5657 }
5658 if($PTName eq "void") {
5659 last;
5660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005661 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005662 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005663 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005664 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005665 $ParamInfoId = getNextElem($ParamInfoId);
5666 next;
5667 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005668 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005669
5670 if(my %Base = get_BaseType($ParamTypeId, $Version))
5671 {
5672 if(defined $Base{"Template"}) {
5673 return 1;
5674 }
5675 }
5676
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005677 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005678 if(my $Algn = getAlgn($ParamInfoId)) {
5679 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005681 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5682 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005683 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005684 }
5685 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005686 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005687 if($ParamName ne "this" or $FType ne "Method") {
5688 $PPos += 1;
5689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005690 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005691 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005692 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005693 }
5694 return 0;
5695}
5696
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005697sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005698{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005699 my ($InfoId, $Vtt_Pos) = @_;
5700 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005701 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005702 my $FType = getFuncType($InfoId);
5703
5704 if($FType eq "Method")
5705 {
5706 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005707 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005708 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005709 if(not $ParamListElemId)
5710 { # foo(...)
5711 return 1;
5712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005713 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005714 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005715 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005716 { # actual params: may differ from formal args
5717 # formal int*const
5718 # actual: int*
5719 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005720 {
5721 $Vtt_Pos=-1;
5722 $ParamListElemId = getNextElem($ParamListElemId);
5723 next;
5724 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005725 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5726 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005727 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005728 $HaveVoid = 1;
5729 last;
5730 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005731 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005732 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005733 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5734 {
5735 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5736 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5737 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005738 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005739 }
5740 }
5741 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5742 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005743 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005744 { # params
5745 if($OldId ne $ParamTypeId)
5746 {
5747 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5748 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5749
5750 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5751 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5752 }
5753 }
5754 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005755 }
5756 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005757 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005758 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005759 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5760 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005761 if($PurpType eq "nop_expr")
5762 { # func ( const char* arg = (const char*)(void*)0 )
5763 $PurpId = getTreeAttr_Op($PurpId);
5764 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005765 my $Val = getInitVal($PurpId, $ParamTypeId);
5766 if(defined $Val) {
5767 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005769 }
5770 }
5771 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005772 if($Pos!=0 or $FType ne "Method") {
5773 $PPos += 1;
5774 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005775 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005776 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005777 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005778}
5779
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005780sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005781{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005782 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5783 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005784 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5785 return $1;
5786 }
5787 }
5788 return "";
5789}
5790
5791sub getTreeAttr_Chain($)
5792{
5793 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5794 {
5795 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5796 return $1;
5797 }
5798 }
5799 return "";
5800}
5801
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005802sub getTreeAttr_Unql($)
5803{
5804 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5805 {
5806 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5807 return $1;
5808 }
5809 }
5810 return "";
5811}
5812
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005813sub getTreeAttr_Scpe($)
5814{
5815 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5816 {
5817 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5818 return $1;
5819 }
5820 }
5821 return "";
5822}
5823
5824sub getTreeAttr_Type($)
5825{
5826 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5827 {
5828 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5829 return $1;
5830 }
5831 }
5832 return "";
5833}
5834
5835sub getTreeAttr_Name($)
5836{
5837 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5838 {
5839 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5840 return $1;
5841 }
5842 }
5843 return "";
5844}
5845
5846sub getTreeAttr_Mngl($)
5847{
5848 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5849 {
5850 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5851 return $1;
5852 }
5853 }
5854 return "";
5855}
5856
5857sub getTreeAttr_Prms($)
5858{
5859 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5860 {
5861 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5862 return $1;
5863 }
5864 }
5865 return "";
5866}
5867
5868sub getTreeAttr_Fncs($)
5869{
5870 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5871 {
5872 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5873 return $1;
5874 }
5875 }
5876 return "";
5877}
5878
5879sub getTreeAttr_Csts($)
5880{
5881 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5882 {
5883 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5884 return $1;
5885 }
5886 }
5887 return "";
5888}
5889
5890sub getTreeAttr_Purp($)
5891{
5892 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5893 {
5894 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5895 return $1;
5896 }
5897 }
5898 return "";
5899}
5900
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005901sub getTreeAttr_Op($)
5902{
5903 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5904 {
5905 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5906 return $1;
5907 }
5908 }
5909 return "";
5910}
5911
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005912sub getTreeAttr_Valu($)
5913{
5914 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5915 {
5916 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5917 return $1;
5918 }
5919 }
5920 return "";
5921}
5922
5923sub getTreeAttr_Flds($)
5924{
5925 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5926 {
5927 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5928 return $1;
5929 }
5930 }
5931 return "";
5932}
5933
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005934sub getTreeAttr_Binf($)
5935{
5936 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5937 {
5938 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5939 return $1;
5940 }
5941 }
5942 return "";
5943}
5944
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005945sub getTreeAttr_Args($)
5946{
5947 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5948 {
5949 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005950 return $1;
5951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005952 }
5953 return "";
5954}
5955
5956sub getTreeValue($)
5957{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005958 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5959 {
5960 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5961 return $1;
5962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005963 }
5964 return "";
5965}
5966
5967sub getTreeAccess($)
5968{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005969 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005970 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005971 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5972 {
5973 my $Access = $1;
5974 if($Access eq "prot") {
5975 return "protected";
5976 }
5977 elsif($Access eq "priv") {
5978 return "private";
5979 }
5980 }
5981 elsif($Info=~/ protected /)
5982 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005983 return "protected";
5984 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005985 elsif($Info=~/ private /)
5986 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 return "private";
5988 }
5989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990 return "public";
5991}
5992
5993sub setFuncAccess($)
5994{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005995 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005997 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005998 }
5999 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006000 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006001 }
6002}
6003
6004sub setTypeAccess($$)
6005{
6006 my ($TypeId, $TypeAttr) = @_;
6007 my $Access = getTreeAccess($TypeId);
6008 if($Access eq "protected") {
6009 $TypeAttr->{"Protected"} = 1;
6010 }
6011 elsif($Access eq "private") {
6012 $TypeAttr->{"Private"} = 1;
6013 }
6014}
6015
6016sub setFuncKind($)
6017{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006018 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6019 {
6020 if($Info=~/pseudo tmpl/) {
6021 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
6022 }
6023 elsif($Info=~/ constructor /) {
6024 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
6025 }
6026 elsif($Info=~/ destructor /) {
6027 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
6028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029 }
6030}
6031
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006032sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006033{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006034 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6035 {
6036 if($Info=~/spec[ ]*:[ ]*pure /) {
6037 return "PureVirt";
6038 }
6039 elsif($Info=~/spec[ ]*:[ ]*virt /) {
6040 return "Virt";
6041 }
6042 elsif($Info=~/ pure\s+virtual /)
6043 { # support for old GCC versions
6044 return "PureVirt";
6045 }
6046 elsif($Info=~/ virtual /)
6047 { # support for old GCC versions
6048 return "Virt";
6049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050 }
6051 return "";
6052}
6053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054sub getFuncLink($)
6055{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006056 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6057 {
6058 if($Info=~/link[ ]*:[ ]*static /) {
6059 return "Static";
6060 }
6061 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062 return $1;
6063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006064 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006065 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066}
6067
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006068sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006069{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006070 my ($Symbol, $LibVersion) = @_;
6071 return "" if(not $Symbol or not $LibVersion);
6072 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6073 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006075 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6076 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6077 }
6078 }
6079 if($NS)
6080 {
6081 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6082 return $NS;
6083 }
6084 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006086 while($NS=~s/::[^:]+\Z//)
6087 {
6088 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6089 return $NS;
6090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006091 }
6092 }
6093 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006094
6095 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006096}
6097
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006098sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099{
6100 my ($TypeName, $LibVersion) = @_;
6101 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006102 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006103 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006104 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6105 return $NS;
6106 }
6107 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006109 while($NS=~s/::[^:]+\Z//)
6110 {
6111 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6112 return $NS;
6113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114 }
6115 }
6116 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006117 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006118}
6119
6120sub getNameSpace($)
6121{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006122 my $InfoId = $_[0];
6123 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006125 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006127 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006128 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006129 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6130 {
6131 my $NameSpace = getTreeStr($1);
6132 if($NameSpace eq "::")
6133 { # global namespace
6134 return "";
6135 }
6136 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6137 $NameSpace = $BaseNameSpace."::".$NameSpace;
6138 }
6139 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6140 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006142 else {
6143 return "";
6144 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006145 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006146 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006147 { # inside data type
6148 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6149 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006151 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006152 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006153 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006154}
6155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006156sub getEnumMembVal($)
6157{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006158 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006159 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006160 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6161 {
6162 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6163 {
6164 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6165 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6166 return getTreeValue($1);
6167 }
6168 else
6169 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6170 return getTreeValue($1);
6171 }
6172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006173 }
6174 }
6175 return "";
6176}
6177
6178sub getSize($)
6179{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006180 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6181 {
6182 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6183 return getTreeValue($1);
6184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006185 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006186 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006187}
6188
6189sub getAlgn($)
6190{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006191 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6192 {
6193 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6194 return $1;
6195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006197 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006198}
6199
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006200sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006201{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006202 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6203 {
6204 if($Info=~/ bitfield /) {
6205 return getSize($_[0]);
6206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006207 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006208 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006209}
6210
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006211sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006212{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006213 if(my $Chan = getTreeAttr_Chan($_[0])) {
6214 return $Chan;
6215 }
6216 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6217 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006218 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006219 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220}
6221
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006222sub registerHeader($$)
6223{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006224 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006225 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006226 return "";
6227 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006228 if(is_abs($Header) and not -f $Header)
6229 { # incorrect absolute path
6230 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006232 if(skipHeader($Header, $LibVersion))
6233 { # skip
6234 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006236 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6237 {
6238 detect_header_includes($Header_Path, $LibVersion);
6239
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006240 if(defined $Tolerance and $Tolerance=~/3/)
6241 { # 3 - skip headers that include non-Linux headers
6242 if($OSgroup ne "windows")
6243 {
6244 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6245 {
6246 if(specificHeader($Inc, "windows")) {
6247 return "";
6248 }
6249 }
6250 }
6251 }
6252
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006253 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6254 { # redirect
6255 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6256 or skipHeader($RHeader_Path, $LibVersion))
6257 { # skip
6258 return "";
6259 }
6260 $Header_Path = $RHeader_Path;
6261 }
6262 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6263 { # skip
6264 return "";
6265 }
6266
6267 if(my $HName = get_filename($Header_Path))
6268 { # register
6269 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6270 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6271 }
6272
6273 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6274 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006275 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006276 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006277 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006278 }
6279
6280 if($CheckHeadersOnly
6281 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6282 { # /usr/include/c++/4.6.1/...
6283 $STDCXX_TESTING = 1;
6284 }
6285
6286 return $Header_Path;
6287 }
6288 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006289}
6290
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006291sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292{
6293 my ($Dir, $WithDeps, $LibVersion) = @_;
6294 $Dir=~s/[\/\\]+\Z//g;
6295 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006297
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006298 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006299 if($WithDeps)
6300 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006301 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6302 return;
6303 }
6304 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6305 $Mode = "DepsOnly";
6306 }
6307 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006308 else
6309 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006310 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6311 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6312 return;
6313 }
6314 }
6315 $Header_Dependency{$LibVersion}{$Dir} = 1;
6316 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6317 if($Mode eq "DepsOnly")
6318 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006319 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006320 $Header_Dependency{$LibVersion}{$Path} = 1;
6321 }
6322 return;
6323 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006324 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006325 {
6326 if($WithDeps)
6327 {
6328 my $SubDir = $Path;
6329 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6330 { # register all sub directories
6331 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6332 }
6333 }
6334 next if(is_not_header($Path));
6335 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006336 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006337 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6339 }
6340 }
6341 if(get_filename($Dir) eq "include")
6342 { # search for "lib/include/" directory
6343 my $LibDir = $Dir;
6344 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006345 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006346 }
6347 }
6348}
6349
6350sub parse_redirect($$$)
6351{
6352 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 my @Errors = ();
6354 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6355 push(@Errors, $1);
6356 }
6357 my $Redirect = "";
6358 foreach (@Errors)
6359 {
6360 s/\s{2,}/ /g;
6361 if(/(only|must\ include
6362 |update\ to\ include
6363 |replaced\ with
6364 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006365 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006366 {
6367 $Redirect = $2;
6368 last;
6369 }
6370 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6371 {
6372 $Redirect = $2;
6373 last;
6374 }
6375 elsif(/this\ header\ should\ not\ be\ used
6376 |programs\ should\ not\ directly\ include
6377 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6378 |is\ not\ supported\ API\ for\ general\ use
6379 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006380 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006381 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6382 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6383 }
6384 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006385 if($Redirect)
6386 {
6387 $Redirect=~s/\A<//g;
6388 $Redirect=~s/>\Z//g;
6389 }
6390 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391}
6392
6393sub parse_includes($$)
6394{
6395 my ($Content, $Path) = @_;
6396 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006397 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006398 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006399 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006400 my $Method = substr($Header, 0, 1, "");
6401 substr($Header, length($Header)-1, 1, "");
6402 $Header = path_format($Header, $OSgroup);
6403 if($Method eq "\"" or is_abs($Header))
6404 {
6405 if(-e join_P(get_dirname($Path), $Header))
6406 { # relative path exists
6407 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006408 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006409 else
6410 { # include "..." that doesn't exist is equal to include <...>
6411 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006413 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006414 else {
6415 $Includes{$Header} = 1;
6416 }
6417 }
6418 if($ExtraInfo)
6419 {
6420 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6421 { # FT_FREETYPE_H
6422 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006423 }
6424 }
6425 return \%Includes;
6426}
6427
6428sub ignore_path($)
6429{
6430 my $Path = $_[0];
6431 if($Path=~/\~\Z/)
6432 {# skipping system backup files
6433 return 1;
6434 }
6435 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6436 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6437 return 1;
6438 }
6439 return 0;
6440}
6441
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006442sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006443{
6444 my ($ArrRef, $W) = @_;
6445 return if(length($W)<2);
6446 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6447}
6448
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006449sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450{
6451 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006453 $H1=~s/\.[a-z]+\Z//ig;
6454 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006455
6456 my $Hname1 = get_filename($H1);
6457 my $Hname2 = get_filename($H2);
6458 my $HDir1 = get_dirname($H1);
6459 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 my $Dirname1 = get_filename($HDir1);
6461 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006462
6463 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6464 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6465
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006466 if($_[0] eq $_[1]
6467 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006468 return 0;
6469 }
6470 elsif($H1=~/\A\Q$H2\E/) {
6471 return 1;
6472 }
6473 elsif($H2=~/\A\Q$H1\E/) {
6474 return -1;
6475 }
6476 elsif($HDir1=~/\Q$Hname1\E/i
6477 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006478 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006479 return -1;
6480 }
6481 elsif($HDir2=~/\Q$Hname2\E/i
6482 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006483 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006484 return 1;
6485 }
6486 elsif($Hname1=~/\Q$Dirname1\E/i
6487 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006488 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006489 return -1;
6490 }
6491 elsif($Hname2=~/\Q$Dirname2\E/i
6492 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006493 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006494 return 1;
6495 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006496 elsif($Hname1=~/(config|lib|util)/i
6497 and $Hname2!~/(config|lib|util)/i)
6498 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006499 return -1;
6500 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006501 elsif($Hname2=~/(config|lib|util)/i
6502 and $Hname1!~/(config|lib|util)/i)
6503 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006504 return 1;
6505 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006506 else
6507 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006508 my $R1 = checkRelevance($H1);
6509 my $R2 = checkRelevance($H2);
6510 if($R1 and not $R2)
6511 { # libebook/e-book.h
6512 return -1;
6513 }
6514 elsif($R2 and not $R1)
6515 { # libebook/e-book.h
6516 return 1;
6517 }
6518 else
6519 {
6520 return (lc($H1) cmp lc($H2));
6521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006522 }
6523}
6524
6525sub searchForHeaders($)
6526{
6527 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006529 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006530 registerGccHeaders();
6531
6532 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6533 { # c++ standard include paths
6534 registerCppHeaders();
6535 }
6536
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006537 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006538 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6539 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006540 {
6541 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006542 if($SystemRoot)
6543 {
6544 if(is_abs($Path)) {
6545 $Path = $SystemRoot.$Path;
6546 }
6547 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006548 if(not -e $Path) {
6549 exitStatus("Access_Error", "can't access \'$Path\'");
6550 }
6551 elsif(-f $Path) {
6552 exitStatus("Access_Error", "\'$Path\' - not a directory");
6553 }
6554 elsif(-d $Path)
6555 {
6556 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006557 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006558 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6559 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006560 }
6561 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006562 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006563 }
6564 }
6565 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006566 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006567 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6568 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006569
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006570 # registering directories
6571 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6572 {
6573 next if(not -e $Path);
6574 $Path = get_abs_path($Path);
6575 $Path = path_format($Path, $OSgroup);
6576 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006577 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006578 }
6579 elsif(-f $Path)
6580 {
6581 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006582 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006583 and not $LocalIncludes{$Dir})
6584 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006585 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006586 # if(my $OutDir = get_dirname($Dir))
6587 # { # registering the outer directory
6588 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6589 # and not $LocalIncludes{$OutDir}) {
6590 # registerDir($OutDir, 0, $LibVersion);
6591 # }
6592 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006593 }
6594 }
6595 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006596
6597 # clean memory
6598 %RegisteredDirs = ();
6599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006600 # registering headers
6601 my $Position = 0;
6602 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6603 {
6604 if(is_abs($Dest) and not -e $Dest) {
6605 exitStatus("Access_Error", "can't access \'$Dest\'");
6606 }
6607 $Dest = path_format($Dest, $OSgroup);
6608 if(is_header($Dest, 1, $LibVersion))
6609 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006610 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006611 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6612 }
6613 }
6614 elsif(-d $Dest)
6615 {
6616 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006617 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006618 {
6619 next if(ignore_path($Path));
6620 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006621 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006622 push(@Registered, $HPath);
6623 }
6624 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006625 @Registered = sort {sortHeaders($a, $b)} @Registered;
6626 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006627 foreach my $Path (@Registered) {
6628 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6629 }
6630 }
6631 else {
6632 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6633 }
6634 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006635
6636 if(defined $Tolerance and $Tolerance=~/4/)
6637 { # 4 - skip headers included by others
6638 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6639 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006640 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006641 delete($Registered_Headers{$LibVersion}{$Path});
6642 }
6643 }
6644 }
6645
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006646 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6647 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006648 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006649 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006650 if(is_abs($Header) and not -f $Header) {
6651 exitStatus("Access_Error", "can't access file \'$Header\'");
6652 }
6653 $Header = path_format($Header, $OSgroup);
6654 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006656 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006657 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006658 }
6659 else {
6660 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006662 }
6663 }
6664 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6665 { # set relative paths (for duplicates)
6666 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6667 { # search for duplicates
6668 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6669 my $Prefix = get_dirname($FirstPath);
6670 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6671 { # detect a shortest distinguishing prefix
6672 my $NewPrefix = $1;
6673 my %Identity = ();
6674 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6675 {
6676 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6677 $Identity{$Path} = $1;
6678 }
6679 }
6680 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6681 { # all names are differend with current prefix
6682 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6683 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6684 }
6685 last;
6686 }
6687 $Prefix = $NewPrefix; # increase prefix
6688 }
6689 }
6690 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006691
6692 # clean memory
6693 %HeaderName_Paths = ();
6694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006695 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6696 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006697 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006698 my ($Pos, $PairPos) = (-1, -1);
6699 my ($Path, $PairPath) = ();
6700 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6701 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6702 foreach my $Header_Path (@Paths)
6703 {
6704 if(get_filename($Header_Path) eq $PairName)
6705 {
6706 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6707 $PairPath = $Header_Path;
6708 }
6709 if(get_filename($Header_Path) eq $HeaderName)
6710 {
6711 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6712 $Path = $Header_Path;
6713 }
6714 }
6715 if($PairPos!=-1 and $Pos!=-1
6716 and int($PairPos)<int($Pos))
6717 {
6718 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6719 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6720 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6721 }
6722 }
6723 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6724 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6725 }
6726}
6727
6728sub detect_real_includes($$)
6729{
6730 my ($AbsPath, $LibVersion) = @_;
6731 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6732 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6733 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6734 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6735 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006736 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6737
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006738 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6739 return () if(not $Path);
6740 open(PREPROC, $Path);
6741 while(<PREPROC>)
6742 {
6743 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6744 {
6745 my $Include = path_format($1, $OSgroup);
6746 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6747 next;
6748 }
6749 if($Include eq $AbsPath) {
6750 next;
6751 }
6752 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6753 }
6754 }
6755 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006756 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6757}
6758
6759sub detect_header_includes($$)
6760{
6761 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006762 return if(not $LibVersion or not $Path);
6763 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6764 return;
6765 }
6766 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6767
6768 if(not -e $Path) {
6769 return;
6770 }
6771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006773 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6774 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006775 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006776 {
6777 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006778 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006779 }
6780 if($RedirectPath ne $Path) {
6781 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6782 }
6783 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006784 else
6785 { # can't find
6786 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006788 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006789 if(my $Inc = parse_includes($Content, $Path))
6790 {
6791 foreach my $Include (keys(%{$Inc}))
6792 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006793 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006794
6795 if(defined $Tolerance and $Tolerance=~/4/)
6796 {
6797 if(my $HPath = identifyHeader($Include, $LibVersion))
6798 {
6799 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6800 }
6801 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006804}
6805
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006806sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006807{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006808 my $Path = $_[0];
6809 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006810 if($OStarget eq "symbian")
6811 {
6812 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6813 { # epoc32/include/libc/{stdio, ...}.h
6814 return 1;
6815 }
6816 }
6817 else
6818 {
6819 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6820 { # /usr/include/{stdio, ...}.h
6821 return 1;
6822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006824 return 0;
6825}
6826
6827sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006828{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006829 my $Dir = $_[0];
6830 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006831 if($OStarget eq "symbian")
6832 {
6833 if(get_filename($OutDir) eq "libc"
6834 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6835 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6836 return 1;
6837 }
6838 }
6839 else
6840 { # linux
6841 if($OutDir eq "/usr/include"
6842 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6843 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6844 return 1;
6845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006846 }
6847 return 0;
6848}
6849
6850sub detect_recursive_includes($$)
6851{
6852 my ($AbsPath, $LibVersion) = @_;
6853 return () if(not $AbsPath);
6854 if(isCyclical(\@RecurInclude, $AbsPath)) {
6855 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6856 }
6857 my ($AbsDir, $Name) = separate_path($AbsPath);
6858 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006859 { # system GLIBC internals
6860 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006861 }
6862 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6863 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6864 }
6865 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006866
6867 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6868 { # skip /usr/include/c++/*/ headers
6869 return () if(not $ExtraInfo);
6870 }
6871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006872 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006873 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006874 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006875 { # check "real" (non-"model") include paths
6876 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6877 pop(@RecurInclude);
6878 return @Paths;
6879 }
6880 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6881 detect_header_includes($AbsPath, $LibVersion);
6882 }
6883 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6884 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006885 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006887 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006888 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006889 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006890 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006891 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006892 }
6893 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006894 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006895 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006896 { # search for the nearest header
6897 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006898 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006899 if(-f $Candidate) {
6900 $HPath = $Candidate;
6901 }
6902 }
6903 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006904 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006905 }
6906 next if(not $HPath);
6907 if($HPath eq $AbsPath) {
6908 next;
6909 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006910
6911 if($Debug)
6912 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006913# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6914# {
6915# print STDERR "$AbsPath -> $HPath\n";
6916# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006917 }
6918
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006919 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6920 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006921 { # only include <...>, skip include "..." prefixes
6922 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6923 }
6924 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6925 {
6926 if($IncPath eq $AbsPath) {
6927 next;
6928 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006929 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6930 if($RIncType==-1)
6931 { # include "..."
6932 $RIncType = $IncType;
6933 }
6934 elsif($RIncType==2)
6935 {
6936 if($IncType!=-1) {
6937 $RIncType = $IncType;
6938 }
6939 }
6940 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006941 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6942 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6943 }
6944 }
6945 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6946 {
6947 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6948 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6949 { # distinguish math.h from glibc and math.h from the tested library
6950 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6951 last;
6952 }
6953 }
6954 }
6955 pop(@RecurInclude);
6956 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6957}
6958
6959sub find_in_framework($$$)
6960{
6961 my ($Header, $Framework, $LibVersion) = @_;
6962 return "" if(not $Header or not $Framework or not $LibVersion);
6963 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6964 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6965 }
6966 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6967 {
6968 if(get_filename($Dependency) eq $Framework
6969 and -f get_dirname($Dependency)."/".$Header) {
6970 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6971 }
6972 }
6973 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6974}
6975
6976sub find_in_defaults($)
6977{
6978 my $Header = $_[0];
6979 return "" if(not $Header);
6980 if(defined $Cache{"find_in_defaults"}{$Header}) {
6981 return $Cache{"find_in_defaults"}{$Header};
6982 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006983 foreach my $Dir (@DefaultIncPaths,
6984 @DefaultGccPaths,
6985 @DefaultCppPaths,
6986 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006987 {
6988 next if(not $Dir);
6989 if(-f $Dir."/".$Header) {
6990 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6991 }
6992 }
6993 return ($Cache{"find_in_defaults"}{$Header}="");
6994}
6995
6996sub cmp_paths($$)
6997{
6998 my ($Path1, $Path2) = @_;
6999 my @Parts1 = split(/[\/\\]/, $Path1);
7000 my @Parts2 = split(/[\/\\]/, $Path2);
7001 foreach my $Num (0 .. $#Parts1)
7002 {
7003 my $Part1 = $Parts1[$Num];
7004 my $Part2 = $Parts2[$Num];
7005 if($GlibcDir{$Part1}
7006 and not $GlibcDir{$Part2}) {
7007 return 1;
7008 }
7009 elsif($GlibcDir{$Part2}
7010 and not $GlibcDir{$Part1}) {
7011 return -1;
7012 }
7013 elsif($Part1=~/glib/
7014 and $Part2!~/glib/) {
7015 return 1;
7016 }
7017 elsif($Part1!~/glib/
7018 and $Part2=~/glib/) {
7019 return -1;
7020 }
7021 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
7022 return $CmpRes;
7023 }
7024 }
7025 return 0;
7026}
7027
7028sub checkRelevance($)
7029{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007030 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007031 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007032
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007033 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007034 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007035 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007036
7037 my $Name = lc(get_filename($Path));
7038 my $Dir = lc(get_dirname($Path));
7039
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007040 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007041
7042 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007043 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007044 my $Len = length($Token);
7045 next if($Len<=1);
7046 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
7047 { # include/evolution-data-server-1.4/libebook/e-book.h
7048 return 1;
7049 }
7050 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007051 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007052 return 1;
7053 }
7054 }
7055 return 0;
7056}
7057
7058sub checkFamily(@)
7059{
7060 my @Paths = @_;
7061 return 1 if($#Paths<=0);
7062 my %Prefix = ();
7063 foreach my $Path (@Paths)
7064 {
7065 if($SystemRoot) {
7066 $Path = cut_path_prefix($Path, $SystemRoot);
7067 }
7068 if(my $Dir = get_dirname($Path))
7069 {
7070 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
7071 $Prefix{$Dir} += 1;
7072 $Prefix{get_dirname($Dir)} += 1;
7073 }
7074 }
7075 foreach (sort keys(%Prefix))
7076 {
7077 if(get_depth($_)>=3
7078 and $Prefix{$_}==$#Paths+1) {
7079 return 1;
7080 }
7081 }
7082 return 0;
7083}
7084
7085sub isAcceptable($$$)
7086{
7087 my ($Header, $Candidate, $LibVersion) = @_;
7088 my $HName = get_filename($Header);
7089 if(get_dirname($Header))
7090 { # with prefix
7091 return 1;
7092 }
7093 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7094 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7095 return 1;
7096 }
7097 if(checkRelevance($Candidate))
7098 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7099 return 1;
7100 }
7101 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7102 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7103 # /usr/include/qt4/Qt/qsslconfiguration.h
7104 return 1;
7105 }
7106 if($OStarget eq "symbian")
7107 {
7108 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7109 return 1;
7110 }
7111 }
7112 return 0;
7113}
7114
7115sub isRelevant($$$)
7116{ # disallow to search for "abstract" headers in too deep directories
7117 my ($Header, $Candidate, $LibVersion) = @_;
7118 my $HName = get_filename($Header);
7119 if($OStarget eq "symbian")
7120 {
7121 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7122 return 0;
7123 }
7124 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007125 if($OStarget ne "bsd")
7126 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7128 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7129 return 0;
7130 }
7131 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007132 if($OStarget ne "windows")
7133 {
7134 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7135 { # skip /usr/include/wine/msvcrt
7136 return 0;
7137 }
7138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007139 if(not get_dirname($Header)
7140 and $Candidate=~/[\/\\]wx[\/\\]/)
7141 { # do NOT search in system /wx/ directory
7142 # for headers without a prefix: sstream.h
7143 return 0;
7144 }
7145 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7146 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7147 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7148 return 0;
7149 }
7150 if($Candidate=~/[\/\\]asm-/
7151 and (my $Arch = getArch($LibVersion)) ne "unknown")
7152 { # arch-specific header files
7153 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7154 {# skip ../asm-arm/ if using x86 architecture
7155 return 0;
7156 }
7157 }
7158 my @Candidates = getSystemHeaders($HName, $LibVersion);
7159 if($#Candidates==1)
7160 { # unique header
7161 return 1;
7162 }
7163 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7164 if($#SCandidates==1)
7165 { # unique name
7166 return 1;
7167 }
7168 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7169 if(get_depth($Candidate)-$SystemDepth>=5)
7170 { # abstract headers in too deep directories
7171 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7172 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7173 return 0;
7174 }
7175 }
7176 if($Header eq "parser.h"
7177 and $Candidate!~/\/libxml2\//)
7178 { # select parser.h from xml2 library
7179 return 0;
7180 }
7181 if(not get_dirname($Header)
7182 and keys(%{$SystemHeaders{$HName}})>=3)
7183 { # many headers with the same name
7184 # like thread.h included without a prefix
7185 if(not checkFamily(@Candidates)) {
7186 return 0;
7187 }
7188 }
7189 return 1;
7190}
7191
7192sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007193{ # cache function
7194 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7195 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7196 }
7197 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7198}
7199
7200sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201{
7202 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007203 if(-f $Header) {
7204 return $Header;
7205 }
7206 if(is_abs($Header) and not -f $Header)
7207 { # incorrect absolute path
7208 return "";
7209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007210 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007211 { # too abstract configuration headers
7212 return "";
7213 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007214 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007215 if($OSgroup ne "windows")
7216 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007217 if(defined $WinHeaders{lc($HName)}
7218 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007219 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007220 return "";
7221 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007222 }
7223 if($OSgroup ne "macos")
7224 {
7225 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007226 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 return "";
7228 }
7229 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007230
7231 if(defined $ObsoleteHeaders{$HName})
7232 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007233 return "";
7234 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007235 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7236 {
7237 if(defined $AlienHeaders{$HName}
7238 or defined $AlienHeaders{$Header})
7239 { # alien headers from other systems
7240 return "";
7241 }
7242 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007243
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007244 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007245 { # search in default paths
7246 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007247 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007248 }
7249 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007250 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007251 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007252 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253 }
7254 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7255 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7256 {
7257 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007258 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 }
7260 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007261 # error
7262 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263}
7264
7265sub getSystemHeaders($$)
7266{
7267 my ($Header, $LibVersion) = @_;
7268 my @Candidates = ();
7269 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007271 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007272 next;
7273 }
7274 push(@Candidates, $Candidate);
7275 }
7276 return @Candidates;
7277}
7278
7279sub cut_path_prefix($$)
7280{
7281 my ($Path, $Prefix) = @_;
7282 return $Path if(not $Prefix);
7283 $Prefix=~s/[\/\\]+\Z//;
7284 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7285 return $Path;
7286}
7287
7288sub is_default_include_dir($)
7289{
7290 my $Dir = $_[0];
7291 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007292 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293}
7294
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007295sub identifyHeader($$)
7296{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007297 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007298 if(not $Header) {
7299 return "";
7300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007301 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007302 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7303 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007304 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007305 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306}
7307
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007308sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309{ # search for header by absolute path, relative path or name
7310 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311 if(-f $Header)
7312 { # it's relative or absolute path
7313 return get_abs_path($Header);
7314 }
7315 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7316 and my $HeaderDir = find_in_defaults($Header))
7317 { # search for libc headers in the /usr/include
7318 # for non-libc target library before searching
7319 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007320 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321 }
7322 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7323 { # search in the target library paths
7324 return $Path;
7325 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007326 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007327 { # search in the internal GCC include paths
7328 return $DefaultGccHeader{$Header};
7329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007330 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007332 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007333 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007334 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007335 { # search in the default G++ include paths
7336 return $DefaultCppHeader{$Header};
7337 }
7338 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7339 { # search everywhere in the system
7340 return $AnyPath;
7341 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007342 elsif($OSgroup eq "macos")
7343 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7344 if(my $Dir = get_dirname($Header))
7345 {
7346 my $RelPath = "Headers\/".get_filename($Header);
7347 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007348 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007349 }
7350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007352 # cannot find anything
7353 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007354}
7355
7356sub getLocation($)
7357{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007358 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7359 {
7360 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007361 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007363 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007364 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007365}
7366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367sub getNameByInfo($)
7368{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007369 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007370 {
7371 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7372 {
7373 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7374 {
7375 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7376 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007377 my $Str = $1;
7378 if($CppMode{$Version}
7379 and $Str=~/\Ac99_(.+)\Z/)
7380 {
7381 if($CppKeywords_A{$1}) {
7382 $Str=$1;
7383 }
7384 }
7385 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007386 }
7387 }
7388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007389 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007390 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391}
7392
7393sub getTreeStr($)
7394{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007395 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007396 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007397 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7398 {
7399 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007400 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007401 and $Str=~/\Ac99_(.+)\Z/)
7402 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007403 if($CppKeywords_A{$1}) {
7404 $Str=$1;
7405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007407 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007410 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007411}
7412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413sub getFuncShortName($)
7414{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007415 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007417 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007418 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007419 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007420 {
7421 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7422 {
7423 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7424 return "operator ".$RName;
7425 }
7426 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007427 }
7428 else
7429 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007430 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7431 {
7432 if(my $Ind = $Operator_Indication{$1}) {
7433 return "operator".$Ind;
7434 }
7435 elsif(not $UnknownOperator{$1})
7436 {
7437 printMsg("WARNING", "unknown operator $1");
7438 $UnknownOperator{$1} = 1;
7439 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007440 }
7441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007442 }
7443 else
7444 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007445 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7446 return getTreeStr($1);
7447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007448 }
7449 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007450 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451}
7452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453sub getFuncReturn($)
7454{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007455 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7456 {
7457 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7458 {
7459 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7460 return $1;
7461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 }
7463 }
7464 return "";
7465}
7466
7467sub getFuncOrig($)
7468{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007469 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7470 {
7471 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7472 return $1;
7473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007474 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007475 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476}
7477
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478sub unmangleArray(@)
7479{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007480 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 { # MSVC mangling
7482 my $UndNameCmd = get_CmdPath("undname");
7483 if(not $UndNameCmd) {
7484 exitStatus("Not_Found", "can't find \"undname\"");
7485 }
7486 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007487 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 }
7489 else
7490 { # GCC mangling
7491 my $CppFiltCmd = get_CmdPath("c++filt");
7492 if(not $CppFiltCmd) {
7493 exitStatus("Not_Found", "can't find c++filt in PATH");
7494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007495 if(not defined $CPPFILT_SUPPORT_FILE)
7496 {
7497 my $Info = `$CppFiltCmd -h 2>&1`;
7498 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7499 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007500 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007501 if($CPPFILT_SUPPORT_FILE)
7502 { # new versions of c++filt can take a file
7503 if($#_>$MAX_CPPFILT_FILE_SIZE)
7504 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7505 # this is fixed in the oncoming version of Binutils
7506 my @Half = splice(@_, 0, ($#_+1)/2);
7507 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007509 else
7510 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007511 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7512 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7513 if($?==139)
7514 { # segmentation fault
7515 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7516 }
7517 return split(/\n/, $Res);
7518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007519 }
7520 else
7521 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007522 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7523 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 my @Half = splice(@_, 0, ($#_+1)/2);
7525 return (unmangleArray(@Half), unmangleArray(@_))
7526 }
7527 else
7528 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007529 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007530 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7531 if($?==139)
7532 { # segmentation fault
7533 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7534 }
7535 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536 }
7537 }
7538 }
7539}
7540
7541sub get_SignatureNoInfo($$)
7542{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 my ($Symbol, $LibVersion) = @_;
7544 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7545 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007547 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007548 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007549 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007551 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7553 $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;
7554 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007555 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007556 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007557 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007558 $Signature .= " [data]";
7559 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007560 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 $Signature .= " (...)";
7562 }
7563 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007564 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007566 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007567 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7568 }
7569 if($SymbolVersion) {
7570 $Signature .= $VersionSpec.$SymbolVersion;
7571 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007572 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007573}
7574
7575sub get_ChargeLevel($$)
7576{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007577 my ($Symbol, $LibVersion) = @_;
7578 return "" if($Symbol!~/\A(_Z|\?)/);
7579 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7580 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007581 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007582 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007583 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007584 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 return "[in-charge]";
7586 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007587 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007588 return "[not-in-charge]";
7589 }
7590 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007591 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007592 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007593 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594 return "[in-charge]";
7595 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007596 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 return "[not-in-charge]";
7598 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007599 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007600 return "[in-charge-deleting]";
7601 }
7602 }
7603 }
7604 else
7605 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007606 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007607 return "[in-charge]";
7608 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007609 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007610 return "[not-in-charge]";
7611 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007612 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613 return "[in-charge]";
7614 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007615 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007616 return "[not-in-charge]";
7617 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007618 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619 return "[in-charge-deleting]";
7620 }
7621 }
7622 return "";
7623}
7624
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007625sub get_Signature_M($$)
7626{
7627 my ($Symbol, $LibVersion) = @_;
7628 my $Signature_M = $tr_name{$Symbol};
7629 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7630 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007631 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007632 }
7633 return $Signature_M;
7634}
7635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007636sub get_Signature($$)
7637{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638 my ($Symbol, $LibVersion) = @_;
7639 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7640 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007641 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007642 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7643 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007644 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007645 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007646 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007647 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007648 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7649 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007650 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007651 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7652 {
7653 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7654 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7655 $Signature .= "~";
7656 }
7657 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007658 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007659 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007660 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007661 }
7662 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007663 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007664 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007665 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7666 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007667 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007668 else
7669 {
7670 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007671 }
7672 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007673 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007674 {
7675 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007676 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007677 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007678 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007679 if(not $ParamTypeName) {
7680 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7681 }
7682 foreach my $Typedef (keys(%ChangedTypedef))
7683 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007684 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7685 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007687 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007688 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7689 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007690 if($ParamName eq "this"
7691 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007692 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007693 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007694 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007695 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007696 }
7697 else {
7698 push(@ParamArray, $ParamTypeName);
7699 }
7700 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007701 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7702 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007703 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007704 }
7705 else
7706 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007707 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007708 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007709 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007711 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007712 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7713 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007714 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007716 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7717 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007718 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007719 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007720 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7721 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007722 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007723 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007724 }
7725 }
7726 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007727 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007728 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007729 }
7730 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007731 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007732 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007733 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007734}
7735
7736sub create_member_decl($$)
7737{
7738 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007739 if($TName=~/\([\*]+\)/)
7740 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007741 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7742 return $TName;
7743 }
7744 else
7745 {
7746 my @ArraySizes = ();
7747 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7748 push(@ArraySizes, $1);
7749 }
7750 return $TName." ".$Member.join("", @ArraySizes);
7751 }
7752}
7753
7754sub getFuncType($)
7755{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007756 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7757 {
7758 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7759 {
7760 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7761 {
7762 if($Type eq "method_type") {
7763 return "Method";
7764 }
7765 elsif($Type eq "function_type") {
7766 return "Function";
7767 }
7768 else {
7769 return "Other";
7770 }
7771 }
7772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007773 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007774 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007775}
7776
7777sub getFuncTypeId($)
7778{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007779 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7780 {
7781 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7782 return $1;
7783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007785 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007786}
7787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007788sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007789{ # "._N" or "$_N" in older GCC versions
7790 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007791}
7792
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007793sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007794{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007795 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7796 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007797 }
7798
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007799 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007800
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007801 if($_[1] ne "S")
7802 {
7803 $N=~s/\A[ ]+//g;
7804 $N=~s/[ ]+\Z//g;
7805 $N=~s/[ ]{2,}/ /g;
7806 }
7807
7808 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007809
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007810 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007811
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007812 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7813 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007814
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007815 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007816
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007817 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007818
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007819 if($_[1] eq "S")
7820 {
7821 if(index($N, "operator")!=-1) {
7822 $N=~s/\b(operator[ ]*)> >/$1>>/;
7823 }
7824 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007825
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007826 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007827}
7828
7829sub get_HeaderDeps($$)
7830{
7831 my ($AbsPath, $LibVersion) = @_;
7832 return () if(not $AbsPath or not $LibVersion);
7833 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7834 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7835 }
7836 my %IncDir = ();
7837 detect_recursive_includes($AbsPath, $LibVersion);
7838 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7839 {
7840 next if(not $HeaderPath);
7841 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7842 my $Dir = get_dirname($HeaderPath);
7843 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7844 {
7845 my $Dep = $Dir;
7846 if($Prefix)
7847 {
7848 if($OSgroup eq "windows")
7849 { # case insensitive seach on windows
7850 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7851 next;
7852 }
7853 }
7854 elsif($OSgroup eq "macos")
7855 { # seach in frameworks
7856 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7857 {
7858 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7859 {# frameworks
7860 my ($HFramework, $HName) = ($1, $2);
7861 $Dep = $HFramework;
7862 }
7863 else
7864 {# mismatch
7865 next;
7866 }
7867 }
7868 }
7869 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7870 { # Linux, FreeBSD
7871 next;
7872 }
7873 }
7874 if(not $Dep)
7875 { # nothing to include
7876 next;
7877 }
7878 if(is_default_include_dir($Dep))
7879 { # included by the compiler
7880 next;
7881 }
7882 if(get_depth($Dep)==1)
7883 { # too short
7884 next;
7885 }
7886 if(isLibcDir($Dep))
7887 { # do NOT include /usr/include/{sys,bits}
7888 next;
7889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007890 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007891 }
7892 }
7893 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7894 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7895}
7896
7897sub sortIncPaths($$)
7898{
7899 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007900 if(not $ArrRef or $#{$ArrRef}<0) {
7901 return $ArrRef;
7902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007903 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7904 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007905 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007906 return $ArrRef;
7907}
7908
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007909sub sortDeps($$$)
7910{
7911 if($Header_Dependency{$_[2]}{$_[0]}
7912 and not $Header_Dependency{$_[2]}{$_[1]}) {
7913 return 1;
7914 }
7915 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7916 and $Header_Dependency{$_[2]}{$_[1]}) {
7917 return -1;
7918 }
7919 return 0;
7920}
7921
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007922sub join_P($$)
7923{
7924 my $S = "/";
7925 if($OSgroup eq "windows") {
7926 $S = "\\";
7927 }
7928 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007929}
7930
7931sub get_namespace_additions($)
7932{
7933 my $NameSpaces = $_[0];
7934 my ($Additions, $AddNameSpaceId) = ("", 1);
7935 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7936 {
7937 next if($SkipNameSpaces{$Version}{$NS});
7938 next if(not $NS or $NameSpaces->{$NS}==-1);
7939 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7940 next if($NS=~/\A__/i);
7941 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007942 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007943 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7944 my @NS_Parts = split(/::/, $NS);
7945 next if($#NS_Parts==-1);
7946 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7947 foreach my $NS_Part (@NS_Parts)
7948 {
7949 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7950 $TypeDecl_Suffix .= "}";
7951 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007952 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007953 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7954 $Additions.=" $TypeDecl\n $FuncDecl\n";
7955 $AddNameSpaceId+=1;
7956 }
7957 return $Additions;
7958}
7959
7960sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007961{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007962 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007963 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007964 if($Fmt eq "windows")
7965 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007966 $Path=~s/\//\\/g;
7967 $Path=lc($Path);
7968 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007969 else
7970 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007971 $Path=~s/\\/\//g;
7972 }
7973 return $Path;
7974}
7975
7976sub inc_opt($$)
7977{
7978 my ($Path, $Style) = @_;
7979 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007980 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007981 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007982 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007983 return "-I\"".path_format($Path, "unix")."\"";
7984 }
7985 elsif($OSgroup eq "macos"
7986 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007987 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007988 return "-F".esc(get_dirname($Path));
7989 }
7990 else {
7991 return "-I".esc($Path);
7992 }
7993 }
7994 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007995 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007996 }
7997 return "";
7998}
7999
8000sub platformSpecs($)
8001{
8002 my $LibVersion = $_[0];
8003 my $Arch = getArch($LibVersion);
8004 if($OStarget eq "symbian")
8005 { # options for GCCE compiler
8006 my %Symbian_Opts = map {$_=>1} (
8007 "-D__GCCE__",
8008 "-DUNICODE",
8009 "-fexceptions",
8010 "-D__SYMBIAN32__",
8011 "-D__MARM_INTERWORK__",
8012 "-D_UNICODE",
8013 "-D__S60_50__",
8014 "-D__S60_3X__",
8015 "-D__SERIES60_3X__",
8016 "-D__EPOC32__",
8017 "-D__MARM__",
8018 "-D__EABI__",
8019 "-D__MARM_ARMV5__",
8020 "-D__SUPPORT_CPP_EXCEPTIONS__",
8021 "-march=armv5t",
8022 "-mapcs",
8023 "-mthumb-interwork",
8024 "-DEKA2",
8025 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
8026 );
8027 return join(" ", keys(%Symbian_Opts));
8028 }
8029 elsif($OSgroup eq "windows"
8030 and get_dumpmachine($GCC_PATH)=~/mingw/i)
8031 { # add options to MinGW compiler
8032 # to simulate the MSVC compiler
8033 my %MinGW_Opts = map {$_=>1} (
8034 "-D_WIN32",
8035 "-D_STDCALL_SUPPORTED",
8036 "-D__int64=\"long long\"",
8037 "-D__int32=int",
8038 "-D__int16=short",
8039 "-D__int8=char",
8040 "-D__possibly_notnullterminated=\" \"",
8041 "-D__nullterminated=\" \"",
8042 "-D__nullnullterminated=\" \"",
8043 "-D__w64=\" \"",
8044 "-D__ptr32=\" \"",
8045 "-D__ptr64=\" \"",
8046 "-D__forceinline=inline",
8047 "-D__inline=inline",
8048 "-D__uuidof(x)=IID()",
8049 "-D__try=",
8050 "-D__except(x)=",
8051 "-D__declspec(x)=__attribute__((x))",
8052 "-D__pragma(x)=",
8053 "-D_inline=inline",
8054 "-D__forceinline=__inline",
8055 "-D__stdcall=__attribute__((__stdcall__))",
8056 "-D__cdecl=__attribute__((__cdecl__))",
8057 "-D__fastcall=__attribute__((__fastcall__))",
8058 "-D__thiscall=__attribute__((__thiscall__))",
8059 "-D_stdcall=__attribute__((__stdcall__))",
8060 "-D_cdecl=__attribute__((__cdecl__))",
8061 "-D_fastcall=__attribute__((__fastcall__))",
8062 "-D_thiscall=__attribute__((__thiscall__))",
8063 "-DSHSTDAPI_(x)=x",
8064 "-D_MSC_EXTENSIONS",
8065 "-DSECURITY_WIN32",
8066 "-D_MSC_VER=1500",
8067 "-D_USE_DECLSPECS_FOR_SAL",
8068 "-D__noop=\" \"",
8069 "-DDECLSPEC_DEPRECATED=\" \"",
8070 "-D__builtin_alignof(x)=__alignof__(x)",
8071 "-DSORTPP_PASS");
8072 if($Arch eq "x86") {
8073 $MinGW_Opts{"-D_M_IX86=300"}=1;
8074 }
8075 elsif($Arch eq "x86_64") {
8076 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8077 }
8078 elsif($Arch eq "ia64") {
8079 $MinGW_Opts{"-D_M_IA64=300"}=1;
8080 }
8081 return join(" ", keys(%MinGW_Opts));
8082 }
8083 return "";
8084}
8085
8086my %C_Structure = map {$_=>1} (
8087# FIXME: Can't separate union and struct data types before dumping,
8088# so it sometimes cause compilation errors for unknown reason
8089# when trying to declare TYPE* tmp_add_class_N
8090# This is a list of such structures + list of other C structures
8091 "sigval",
8092 "sigevent",
8093 "sigaction",
8094 "sigvec",
8095 "sigstack",
8096 "timeval",
8097 "timezone",
8098 "rusage",
8099 "rlimit",
8100 "wait",
8101 "flock",
8102 "stat",
8103 "_stat",
8104 "stat32",
8105 "_stat32",
8106 "stat64",
8107 "_stat64",
8108 "_stati64",
8109 "if_nameindex",
8110 "usb_device",
8111 "sigaltstack",
8112 "sysinfo",
8113 "timeLocale",
8114 "tcp_debug",
8115 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008116 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008117 "timespec",
8118 "random_data",
8119 "drand48_data",
8120 "_IO_marker",
8121 "_IO_FILE",
8122 "lconv",
8123 "sched_param",
8124 "tm",
8125 "itimerspec",
8126 "_pthread_cleanup_buffer",
8127 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008128 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008129 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008130 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008131 "sigcontext",
8132 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008133 # Mac
8134 "_timex",
8135 "_class_t",
8136 "_category_t",
8137 "_class_ro_t",
8138 "_protocol_t",
8139 "_message_ref_t",
8140 "_super_message_ref_t",
8141 "_ivar_t",
8142 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008143);
8144
8145sub getCompileCmd($$$)
8146{
8147 my ($Path, $Opt, $Inc) = @_;
8148 my $GccCall = $GCC_PATH;
8149 if($Opt) {
8150 $GccCall .= " ".$Opt;
8151 }
8152 $GccCall .= " -x ";
8153 if($OSgroup eq "macos") {
8154 $GccCall .= "objective-";
8155 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008156
8157 if($EMERGENCY_MODE_48)
8158 { # workaround for GCC 4.8 (C only)
8159 $GccCall .= "c++";
8160 }
8161 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008162 { # compile as "C++" header
8163 # to obtain complete dump using GCC 4.0
8164 $GccCall .= "c++-header";
8165 }
8166 else
8167 { # compile as "C++" source
8168 # GCC 3.3 cannot compile headers
8169 $GccCall .= "c++";
8170 }
8171 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008172 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008173 $GccCall .= " ".$Opts;
8174 }
8175 # allow extra qualifications
8176 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008177 $GccCall .= " -fpermissive";
8178 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008179 if($NoStdInc)
8180 {
8181 $GccCall .= " -nostdinc";
8182 $GccCall .= " -nostdinc++";
8183 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008184 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008185 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008186 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008187 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008188 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008189 if($Inc)
8190 { # include paths
8191 $GccCall .= " ".$Inc;
8192 }
8193 return $GccCall;
8194}
8195
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008196sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008197{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008198 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008199 my %HeaderElems = (
8200 # Types
8201 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008202 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008203 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8204 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008205 "time.h" => ["time_t"],
8206 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008207 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8208 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008209 "stdbool.h" => ["_Bool"],
8210 "rpc/xdr.h" => ["bool_t"],
8211 "in_systm.h" => ["n_long", "n_short"],
8212 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008213 "arpa/inet.h" => ["fw_src", "ip_src"],
8214 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008215 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008216 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008217 );
8218 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008219 foreach (keys(%HeaderElems))
8220 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008221 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008222 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008223 }
8224 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008225 my %Types = ();
8226 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8227 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008228 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008229 }
8230 if(keys(%Types))
8231 {
8232 my %AddHeaders = ();
8233 foreach my $Type (keys(%Types))
8234 {
8235 if(my $Header = $AutoPreamble{$Type})
8236 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008237 if(my $Path = identifyHeader($Header, $LibVersion))
8238 {
8239 if(skipHeader($Path, $LibVersion)) {
8240 next;
8241 }
8242 $Path = path_format($Path, $OSgroup);
8243 $AddHeaders{$Path}{"Type"} = $Type;
8244 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008245 }
8246 }
8247 }
8248 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008249 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008250 }
8251 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008252 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008253}
8254
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008255sub checkCTags($)
8256{
8257 my $Path = $_[0];
8258 if(not $Path) {
8259 return;
8260 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008261 my $CTags = undef;
8262
8263 if($OSgroup eq "bsd")
8264 { # use ectags on BSD
8265 $CTags = get_CmdPath("ectags");
8266 if(not $CTags) {
8267 printMsg("WARNING", "can't find \'ectags\' program");
8268 }
8269 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008270 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008271 $CTags = get_CmdPath("ctags");
8272 }
8273 if(not $CTags)
8274 {
8275 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008276 return;
8277 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008278
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008279 if($OSgroup ne "linux")
8280 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008281 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8282 if($Info!~/exuberant/i)
8283 {
8284 printMsg("WARNING", "incompatible version of \'ctags\' program");
8285 return;
8286 }
8287 }
8288
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008289 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008290 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008291 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008292 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008293 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008294 open(CTAGS, "<", $Out);
8295 while(my $Line = <CTAGS>)
8296 {
8297 chomp($Line);
8298 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008299 if(defined $Intrinsic_Keywords{$Name})
8300 { # noise
8301 next;
8302 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008303 if($Type eq "n")
8304 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008305 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008306 next;
8307 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008308 if(index($Scpe, "struct:")==0) {
8309 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008310 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008311 if(index($Scpe, "namespace:")==0)
8312 {
8313 if($Scpe=~s/\Anamespace://) {
8314 $Name = $Scpe."::".$Name;
8315 }
8316 }
8317 $TUnit_NameSpaces{$Version}{$Name} = 1;
8318 }
8319 elsif($Type eq "p")
8320 {
8321 if(not $Scpe or index($Scpe, "namespace:")==0) {
8322 $TUnit_Funcs{$Version}{$Name} = 1;
8323 }
8324 }
8325 elsif($Type eq "x")
8326 {
8327 if(not $Scpe or index($Scpe, "namespace:")==0) {
8328 $TUnit_Vars{$Version}{$Name} = 1;
8329 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008330 }
8331 }
8332 close(CTAGS);
8333}
8334
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008335sub preChange($$)
8336{
8337 my ($HeaderPath, $IncStr) = @_;
8338
8339 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8340 my $Content = undef;
8341
8342 if($OStarget eq "windows"
8343 and get_dumpmachine($GCC_PATH)=~/mingw/i
8344 and $MinGWMode{$Version}!=-1)
8345 { # modify headers to compile by MinGW
8346 if(not $Content)
8347 { # preprocessing
8348 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8349 }
8350 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8351 { # __asm { ... }
8352 $MinGWMode{$Version}=1;
8353 }
8354 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8355 { # comments after preprocessing
8356 $MinGWMode{$Version}=1;
8357 }
8358 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8359 { # 0xffui8
8360 $MinGWMode{$Version}=1;
8361 }
8362
8363 if($MinGWMode{$Version}) {
8364 printMsg("INFO", "Using MinGW compatibility mode");
8365 }
8366 }
8367
8368 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8369 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8370 { # rename C++ keywords in C code
8371 # disable this code by -cpp-compatible option
8372 if(not $Content)
8373 { # preprocessing
8374 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8375 }
8376 my $RegExp_C = join("|", keys(%CppKeywords_C));
8377 my $RegExp_F = join("|", keys(%CppKeywords_F));
8378 my $RegExp_O = join("|", keys(%CppKeywords_O));
8379
8380 my $Detected = undef;
8381
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008382 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 +04008383 { # MATCH:
8384 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008385 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008386 # unsigned private: 8;
8387 # DO NOT MATCH:
8388 # #pragma GCC visibility push(default)
8389 $CppMode{$Version} = 1;
8390 $Detected = "$1$2$3$4" if(not defined $Detected);
8391 }
8392 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8393 { # MATCH:
8394 # int delete(...);
8395 # int explicit(...);
8396 # DO NOT MATCH:
8397 # void operator delete(...)
8398 $CppMode{$Version} = 1;
8399 $Detected = "$1$2$3" if(not defined $Detected);
8400 }
8401 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8402 { # MATCH:
8403 # int bool;
8404 # DO NOT MATCH:
8405 # bool X;
8406 # return *this;
8407 # throw;
8408 $CppMode{$Version} = 1;
8409 $Detected = "$1$2$3" if(not defined $Detected);
8410 }
8411 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8412 { # MATCH:
8413 # int operator(...);
8414 # DO NOT MATCH:
8415 # int operator()(...);
8416 $CppMode{$Version} = 1;
8417 $Detected = "$1$2$3" if(not defined $Detected);
8418 }
8419 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8420 { # MATCH:
8421 # int foo(int operator);
8422 # int foo(int operator, int other);
8423 # DO NOT MATCH:
8424 # int operator,(...);
8425 $CppMode{$Version} = 1;
8426 $Detected = "$1$2$3" if(not defined $Detected);
8427 }
8428 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8429 { # MATCH:
8430 # int foo(gboolean *bool);
8431 # DO NOT MATCH:
8432 # void setTabEnabled(int index, bool);
8433 $CppMode{$Version} = 1;
8434 $Detected = "$1$2$3" if(not defined $Detected);
8435 }
8436 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8437 { # MATCH:
8438 # int foo(int* this);
8439 # int bar(int this);
8440 # int baz(int throw);
8441 # DO NOT MATCH:
8442 # foo(X, this);
8443 $CppMode{$Version} = 1;
8444 $Detected = "$1$2$3$4" if(not defined $Detected);
8445 }
8446 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8447 { # MATCH:
8448 # struct template {...};
8449 # extern template foo(...);
8450 $CppMode{$Version} = 1;
8451 $Detected = "$1$2" if(not defined $Detected);
8452 }
8453
8454 if($CppMode{$Version} == 1)
8455 {
8456 if($Debug)
8457 {
8458 $Detected=~s/\A\s+//g;
8459 printMsg("INFO", "Detected code: \"$Detected\"");
8460 }
8461 }
8462
8463 # remove typedef enum NAME NAME;
8464 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8465 my $N = 0;
8466 while($N<=$#FwdTypedefs-1)
8467 {
8468 my $S = $FwdTypedefs[$N];
8469 if($S eq $FwdTypedefs[$N+1])
8470 {
8471 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008472 $CppMode{$Version} = 1;
8473
8474 if($Debug) {
8475 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8476 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008477 }
8478 $N+=2;
8479 }
8480
8481 if($CppMode{$Version}==1) {
8482 printMsg("INFO", "Using C++ compatibility mode");
8483 }
8484 }
8485
8486 if($CppMode{$Version}==1
8487 or $MinGWMode{$Version}==1)
8488 {
8489 my $IPath = $TMP_DIR."/dump$Version.i";
8490 writeFile($IPath, $Content);
8491 return $IPath;
8492 }
8493
8494 return undef;
8495}
8496
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008497sub getDump()
8498{
8499 if(not $GCC_PATH) {
8500 exitStatus("Error", "internal error - GCC path is not set");
8501 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008502
8503 my @Headers = keys(%{$Registered_Headers{$Version}});
8504 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8505
8506 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8507
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008508 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008509 my $HeaderPath = $TmpHeaderPath;
8510
8511 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008512 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008513 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8514 {
8515 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008516 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008517 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008518 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008519 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8520 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008521 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008522 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008524 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8525 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008528 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008529
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008530 if($ExtraInfo)
8531 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008532 if($IncludeString) {
8533 writeFile($ExtraInfo."/include-string", $IncludeString);
8534 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008535 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8536 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008537
8538 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8539 {
8540 my $REDIR = "";
8541 foreach my $P1 (sort @Redirects) {
8542 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8543 }
8544 writeFile($ExtraInfo."/include-redirect", $REDIR);
8545 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008546 }
8547
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008548 if(not keys(%{$TargetHeaders{$Version}}))
8549 { # Target headers
8550 addTargetHeaders($Version);
8551 }
8552
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008553 # clean memory
8554 %RecursiveIncludes = ();
8555 %Header_Include_Prefix = ();
8556 %Header_Includes = ();
8557
8558 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008559 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008560 delete($Cache{"detect_header_includes"});
8561 delete($Cache{"selectSystemHeader"});
8562
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008563 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008564 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8565 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008566
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008567 if($ExtraInfo)
8568 { # extra information for other tools
8569 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8570 }
8571
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008572 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008573 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008574 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008575
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008576 if($COMMON_LANGUAGE{$Version} eq "C++") {
8577 checkCTags($Pre);
8578 }
8579
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008580 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8581 { # try to correct the preprocessor output
8582 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008583 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008585 if($COMMON_LANGUAGE{$Version} eq "C++")
8586 { # add classes and namespaces to the dump
8587 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008588 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008589 or $MinGWMode{$Version}==1) {
8590 $CHdump .= " -fpreprocessed";
8591 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008592 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008593 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008594 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 chdir($ORIG_DIR);
8596 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8597 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008598 my $Content = readFile($ClassDump);
8599 foreach my $ClassInfo (split(/\n\n/, $Content))
8600 {
8601 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8602 {
8603 my $CName = $1;
8604 next if($CName=~/\A(__|_objc_|_opaque_)/);
8605 $TUnit_NameSpaces{$Version}{$CName} = -1;
8606 if($CName=~/\A[\w:]+\Z/)
8607 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008608 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008609 }
8610 if($CName=~/(\w[\w:]*)::/)
8611 { # namespaces
8612 my $NS = $1;
8613 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8614 $TUnit_NameSpaces{$Version}{$NS} = 1;
8615 }
8616 }
8617 }
8618 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8619 { # read v-tables (advanced approach)
8620 my ($CName, $VTable) = ($1, $2);
8621 $ClassVTable_Content{$Version}{$CName} = $VTable;
8622 }
8623 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008624 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8625 { # add user-defined namespaces
8626 $TUnit_NameSpaces{$Version}{$NS} = 1;
8627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008628 if($Debug)
8629 { # debug mode
8630 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008631 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008632 }
8633 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008634 }
8635
8636 # add namespaces and classes
8637 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8638 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008639 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008640 }
8641 # some GCC versions don't include class methods to the TU dump by default
8642 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008643 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008644 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8645 {
8646 next if($C_Structure{$CName});
8647 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008648 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008649 if(not $Force and $GCC_44
8650 and $OSgroup eq "linux")
8651 { # optimization for linux with GCC >= 4.4
8652 # disable this code by -force option
8653 if(index($CName, "::")!=-1)
8654 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008655 next;
8656 }
8657 }
8658 else
8659 {
8660 if($CName=~/\A(.+)::[^:]+\Z/
8661 and $TUnit_Classes{$Version}{$1})
8662 { # classes inside other classes
8663 next;
8664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008665 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008666 if(defined $TUnit_Funcs{$Version}{$CName})
8667 { # the same name for a function and type
8668 next;
8669 }
8670 if(defined $TUnit_Vars{$Version}{$CName})
8671 { # the same name for a variable and type
8672 next;
8673 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008674 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8675 }
8676 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008677 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008678 }
8679 }
8680 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8681 # create TU dump
8682 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008683 if($UserLang eq "C") {
8684 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8685 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008686 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 or $MinGWMode{$Version}==1) {
8688 $TUdump .= " -fpreprocessed";
8689 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008690 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008691 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8692 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008693 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008694 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695 if($?)
8696 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008697 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008698 { # try to recompile
8699 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008700 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008701 and index($Errors, "c99_")!=-1
8702 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008703 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008704 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008705
8706 if($Debug)
8707 {
8708 # printMsg("INFO", $Errors);
8709 }
8710
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008711 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008712 resetLogging($Version);
8713 $TMP_DIR = tempdir(CLEANUP=>1);
8714 return getDump();
8715 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008716 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008717 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008718 { # add auto preamble headers and try again
8719 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008720 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008721 foreach my $Num (0 .. $#Headers)
8722 {
8723 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008724 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8725 {
8726 push_U($Include_Preamble{$Version}, $Path);
8727 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008728 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008729 }
8730 resetLogging($Version);
8731 $TMP_DIR = tempdir(CLEANUP=>1);
8732 return getDump();
8733 }
8734 elsif($Cpp0xMode{$Version}!=-1
8735 and ($Errors=~/\Q-std=c++0x\E/
8736 or $Errors=~/is not a class or namespace/))
8737 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008738 if(check_gcc($GCC_PATH, "4.6"))
8739 {
8740 $Cpp0xMode{$Version}=-1;
8741 printMsg("INFO", "Enabling c++0x mode");
8742 resetLogging($Version);
8743 $TMP_DIR = tempdir(CLEANUP=>1);
8744 $CompilerOptions{$Version} .= " -std=c++0x";
8745 return getDump();
8746 }
8747 else {
8748 printMsg("WARNING", "Probably c++0x construction detected");
8749 }
8750
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008751 }
8752 elsif($MinGWMode{$Version}==1)
8753 { # disable MinGW mode and try again
8754 $MinGWMode{$Version}=-1;
8755 resetLogging($Version);
8756 $TMP_DIR = tempdir(CLEANUP=>1);
8757 return getDump();
8758 }
8759 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008760 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008761 else {
8762 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008764 printMsg("ERROR", "some errors occurred when compiling headers");
8765 printErrorLog($Version);
8766 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008767 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008768 }
8769 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008770 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008771 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008772
8773 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8774 return $TUs[0];
8775 }
8776 else
8777 {
8778 my $Msg = "can't compile header(s)";
8779 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8780 $Msg .= "\nDid you install G++?";
8781 }
8782 exitStatus("Cannot_Compile", $Msg);
8783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784}
8785
8786sub cmd_file($)
8787{
8788 my $Path = $_[0];
8789 return "" if(not $Path or not -e $Path);
8790 if(my $CmdPath = get_CmdPath("file")) {
8791 return `$CmdPath -b \"$Path\"`;
8792 }
8793 return "";
8794}
8795
8796sub getIncString($$)
8797{
8798 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008799 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 my $String = "";
8801 foreach (@{$ArrRef}) {
8802 $String .= " ".inc_opt($_, $Style);
8803 }
8804 return $String;
8805}
8806
8807sub getIncPaths(@)
8808{
8809 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008810 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 if($INC_PATH_AUTODETECT{$Version})
8812 { # auto-detecting dependencies
8813 my %Includes = ();
8814 foreach my $HPath (@HeaderPaths)
8815 {
8816 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8817 {
8818 if($Skip_Include_Paths{$Version}{$Dir}) {
8819 next;
8820 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008821 if($SystemRoot)
8822 {
8823 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8824 next;
8825 }
8826 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008827 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008828 }
8829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008830 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008831 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 }
8833 }
8834 else
8835 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008836 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008837 }
8838 return \@IncPaths;
8839}
8840
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008841sub push_U($@)
8842{ # push unique
8843 if(my $Array = shift @_)
8844 {
8845 if(@_)
8846 {
8847 my %Exist = map {$_=>1} @{$Array};
8848 foreach my $Elem (@_)
8849 {
8850 if(not defined $Exist{$Elem})
8851 {
8852 push(@{$Array}, $Elem);
8853 $Exist{$Elem} = 1;
8854 }
8855 }
8856 }
8857 }
8858}
8859
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008860sub callPreprocessor($$$)
8861{
8862 my ($Path, $Inc, $LibVersion) = @_;
8863 return "" if(not $Path or not -f $Path);
8864 my $IncludeString=$Inc;
8865 if(not $Inc) {
8866 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8867 }
8868 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008869 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008870 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008871 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008872}
8873
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008874sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875{ # native "find" is much faster than File::Find (~6x)
8876 # also the File::Find doesn't support --maxdepth N option
8877 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008878 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 return () if(not $Path or not -e $Path);
8880 if($OSgroup eq "windows")
8881 {
8882 my $DirCmd = get_CmdPath("dir");
8883 if(not $DirCmd) {
8884 exitStatus("Not_Found", "can't find \"dir\" command");
8885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008886 $Path = get_abs_path($Path);
8887 $Path = path_format($Path, $OSgroup);
8888 my $Cmd = $DirCmd." \"$Path\" /B /O";
8889 if($MaxDepth!=1) {
8890 $Cmd .= " /S";
8891 }
8892 if($Type eq "d") {
8893 $Cmd .= " /AD";
8894 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008895 elsif($Type eq "f") {
8896 $Cmd .= " /A-D";
8897 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008898 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008899 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008900 {
8901 if(not $UseRegex)
8902 { # FIXME: how to search file names in MS shell?
8903 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008904 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008905 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008906 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008907 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008908 }
8909 my @AbsPaths = ();
8910 foreach my $File (@Files)
8911 {
8912 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008913 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008914 }
8915 if($Type eq "f" and not -f $File)
8916 { # skip dirs
8917 next;
8918 }
8919 push(@AbsPaths, path_format($File, $OSgroup));
8920 }
8921 if($Type eq "d") {
8922 push(@AbsPaths, $Path);
8923 }
8924 return @AbsPaths;
8925 }
8926 else
8927 {
8928 my $FindCmd = get_CmdPath("find");
8929 if(not $FindCmd) {
8930 exitStatus("Not_Found", "can't find a \"find\" command");
8931 }
8932 $Path = get_abs_path($Path);
8933 if(-d $Path and -l $Path
8934 and $Path!~/\/\Z/)
8935 { # for directories that are symlinks
8936 $Path.="/";
8937 }
8938 my $Cmd = $FindCmd." \"$Path\"";
8939 if($MaxDepth) {
8940 $Cmd .= " -maxdepth $MaxDepth";
8941 }
8942 if($Type) {
8943 $Cmd .= " -type $Type";
8944 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008945 if($Name and not $UseRegex)
8946 { # wildcards
8947 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008948 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008949 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008950 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008951 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8952 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008953 my @Files = split(/\n/, $Res);
8954 if($Name and $UseRegex)
8955 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008956 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008957 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008958 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008959 }
8960}
8961
8962sub unpackDump($)
8963{
8964 my $Path = $_[0];
8965 return "" if(not $Path or not -e $Path);
8966 $Path = get_abs_path($Path);
8967 $Path = path_format($Path, $OSgroup);
8968 my ($Dir, $FileName) = separate_path($Path);
8969 my $UnpackDir = $TMP_DIR."/unpack";
8970 rmtree($UnpackDir);
8971 mkpath($UnpackDir);
8972 if($FileName=~s/\Q.zip\E\Z//g)
8973 { # *.zip
8974 my $UnzipCmd = get_CmdPath("unzip");
8975 if(not $UnzipCmd) {
8976 exitStatus("Not_Found", "can't find \"unzip\" command");
8977 }
8978 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008979 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008980 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008981 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008982 }
8983 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008984 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008985 if(not @Contents) {
8986 exitStatus("Error", "can't extract \'$Path\'");
8987 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008988 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008989 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008990 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008991 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008992 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008993 if($OSgroup eq "windows")
8994 { # -xvzf option is not implemented in tar.exe (2003)
8995 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8996 my $TarCmd = get_CmdPath("tar");
8997 if(not $TarCmd) {
8998 exitStatus("Not_Found", "can't find \"tar\" command");
8999 }
9000 my $GzipCmd = get_CmdPath("gzip");
9001 if(not $GzipCmd) {
9002 exitStatus("Not_Found", "can't find \"gzip\" command");
9003 }
9004 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009005 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009006 if($?) {
9007 exitStatus("Error", "can't extract \'$Path\'");
9008 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009009 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009010 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009011 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009012 }
9013 chdir($ORIG_DIR);
9014 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009015 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009016 if(not @Contents) {
9017 exitStatus("Error", "can't extract \'$Path\'");
9018 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009019 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009020 }
9021 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009022 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009023 my $TarCmd = get_CmdPath("tar");
9024 if(not $TarCmd) {
9025 exitStatus("Not_Found", "can't find \"tar\" command");
9026 }
9027 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009028 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009029 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009030 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009031 }
9032 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009033 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009034 if(not @Contents) {
9035 exitStatus("Error", "can't extract \'$Path\'");
9036 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009037 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009038 }
9039 }
9040}
9041
9042sub createArchive($$)
9043{
9044 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009045 if(not $To) {
9046 $To = ".";
9047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009048 if(not $Path or not -e $Path
9049 or not -d $To) {
9050 return "";
9051 }
9052 my ($From, $Name) = separate_path($Path);
9053 if($OSgroup eq "windows")
9054 { # *.zip
9055 my $ZipCmd = get_CmdPath("zip");
9056 if(not $ZipCmd) {
9057 exitStatus("Not_Found", "can't find \"zip\"");
9058 }
9059 my $Pkg = $To."/".$Name.".zip";
9060 unlink($Pkg);
9061 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009062 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009063 if($?)
9064 { # cannot allocate memory (or other problems with "zip")
9065 unlink($Path);
9066 exitStatus("Error", "can't pack the ABI dump: ".$!);
9067 }
9068 chdir($ORIG_DIR);
9069 unlink($Path);
9070 return $Pkg;
9071 }
9072 else
9073 { # *.tar.gz
9074 my $TarCmd = get_CmdPath("tar");
9075 if(not $TarCmd) {
9076 exitStatus("Not_Found", "can't find \"tar\"");
9077 }
9078 my $GzipCmd = get_CmdPath("gzip");
9079 if(not $GzipCmd) {
9080 exitStatus("Not_Found", "can't find \"gzip\"");
9081 }
9082 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
9083 unlink($Pkg);
9084 chdir($From);
9085 system($TarCmd, "-czf", $Pkg, $Name);
9086 if($?)
9087 { # cannot allocate memory (or other problems with "tar")
9088 unlink($Path);
9089 exitStatus("Error", "can't pack the ABI dump: ".$!);
9090 }
9091 chdir($ORIG_DIR);
9092 unlink($Path);
9093 return $To."/".$Name.".tar.gz";
9094 }
9095}
9096
9097sub is_header_file($)
9098{
9099 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9100 return $_[0];
9101 }
9102 return 0;
9103}
9104
9105sub is_not_header($)
9106{
9107 if($_[0]=~/\.\w+\Z/
9108 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9109 return 1;
9110 }
9111 return 0;
9112}
9113
9114sub is_header($$$)
9115{
9116 my ($Header, $UserDefined, $LibVersion) = @_;
9117 return 0 if(-d $Header);
9118 if(-f $Header) {
9119 $Header = get_abs_path($Header);
9120 }
9121 else
9122 {
9123 if(is_abs($Header))
9124 { # incorrect absolute path
9125 return 0;
9126 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009127 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009128 $Header = $HPath;
9129 }
9130 else
9131 { # can't find header
9132 return 0;
9133 }
9134 }
9135 if($Header=~/\.\w+\Z/)
9136 { # have an extension
9137 return is_header_file($Header);
9138 }
9139 else
9140 {
9141 if($UserDefined==2)
9142 { # specified on the command line
9143 if(cmd_file($Header)!~/HTML|XML/i) {
9144 return $Header;
9145 }
9146 }
9147 elsif($UserDefined)
9148 { # specified in the XML-descriptor
9149 # header file without an extension
9150 return $Header;
9151 }
9152 else
9153 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009154 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009155 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009156 { # !~/HTML|XML|shared|dynamic/i
9157 return $Header;
9158 }
9159 }
9160 }
9161 return 0;
9162}
9163
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009164sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009165{
9166 my $LibVersion = $_[0];
9167 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9168 {
9169 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009170 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009171
9172 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9173 detect_recursive_includes($RegHeader, $LibVersion);
9174 }
9175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009176 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9177 {
9178 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009179
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009180 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009181 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9182 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009183 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009184 }
9185 }
9186 }
9187}
9188
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009189sub familiarDirs($$)
9190{
9191 my ($D1, $D2) = @_;
9192 if($D1 eq $D2) {
9193 return 1;
9194 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009195
9196 my $U1 = index($D1, "/usr/");
9197 my $U2 = index($D2, "/usr/");
9198
9199 if($U1==0 and $U2!=0) {
9200 return 0;
9201 }
9202
9203 if($U2==0 and $U1!=0) {
9204 return 0;
9205 }
9206
9207 if(index($D2, $D1."/")==0) {
9208 return 1;
9209 }
9210
9211 # /usr/include/DIR
9212 # /home/user/DIR
9213
9214 my $DL = get_depth($D1);
9215
9216 my @Dirs1 = ($D1);
9217 while($DL - get_depth($D1)<=2
9218 and get_depth($D1)>=4
9219 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9220 push(@Dirs1, $D1);
9221 }
9222
9223 my @Dirs2 = ($D2);
9224 while(get_depth($D2)>=4
9225 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9226 push(@Dirs2, $D2);
9227 }
9228
9229 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009230 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009231 foreach my $P2 (@Dirs2)
9232 {
9233
9234 if($P1 eq $P2) {
9235 return 1;
9236 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009237 }
9238 }
9239 return 0;
9240}
9241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009242sub readHeaders($)
9243{
9244 $Version = $_[0];
9245 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9246 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009247 if($Debug)
9248 { # debug mode
9249 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009250 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009251 }
9252 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009253}
9254
9255sub prepareTypes($)
9256{
9257 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009258 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009259 { # support for old ABI dumps
9260 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009261 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009263 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9264 if($TName=~/\A(\w+)::(\w+)/) {
9265 my ($P1, $P2) = ($1, $2);
9266 if($P1 eq $P2) {
9267 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009269 else {
9270 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009272 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009273 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009274 }
9275 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009276 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009277 { # support for old ABI dumps
9278 # V < 2.5: array size == "number of elements"
9279 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009280 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009282 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009283 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009284 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009285 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009286 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009287 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009288 $Size *= $Base{"Size"};
9289 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009290 }
9291 else
9292 { # array[] is a pointer
9293 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009294 }
9295 }
9296 }
9297 }
9298 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009299 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009300 { # support for old ABI dumps
9301 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009302 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009303 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009304 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009305 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009306 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009307 my %Type = get_Type($TypeId, $LibVersion);
9308 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9309 my %Type2 = get_Type($TypeId_2, $V2);
9310 if($Type{"Size"} ne $Type2{"Size"}) {
9311 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009312 }
9313 }
9314 }
9315 }
9316}
9317
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009318sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009319{
9320 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009321
9322 if(not keys(%{$SymbolInfo{$LibVersion}}))
9323 { # check if input is valid
9324 if(not $ExtendedCheck and not $CheckObjectsOnly)
9325 {
9326 if($CheckHeadersOnly) {
9327 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9328 }
9329 else {
9330 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9331 }
9332 }
9333 }
9334
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009335 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009336 if(not checkDump(1, "2.10")
9337 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009338 { # different formats
9339 $Remangle = 1;
9340 }
9341 if($CheckHeadersOnly)
9342 { # different languages
9343 if($UserLang)
9344 { # --lang=LANG for both versions
9345 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9346 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9347 {
9348 if($UserLang eq "C++")
9349 { # remangle symbols
9350 $Remangle = 1;
9351 }
9352 elsif($UserLang eq "C")
9353 { # remove mangling
9354 $Remangle = -1;
9355 }
9356 }
9357 }
9358 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009359
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009360 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009362 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009363 { # support for old ABI dumps
9364 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9365 {
9366 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9367 {
9368 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9369 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009370 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009371 if(defined $DVal and $DVal ne "")
9372 {
9373 if($TName eq "char") {
9374 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9375 }
9376 elsif($TName eq "bool") {
9377 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9378 }
9379 }
9380 }
9381 }
9382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009383 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009384 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009385 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9386 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009387 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009388 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9389 # + support for old ABI dumps
9390 next;
9391 }
9392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009393 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009394 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009395 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009396 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009397
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009398 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009399 if(not checkDump(1, "2.12")
9400 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009401 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009402 if($ShortName eq "operator>>")
9403 {
9404 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9405 { # corrected mangling of operator>>
9406 $SRemangle = 1;
9407 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009408 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009409 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9410 {
9411 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9412 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9413 { # corrected mangling of const global data
9414 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9415 # and incorrectly mangled by old ACC versions
9416 $SRemangle = 1;
9417 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009418 }
9419 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009420 if(not $CheckHeadersOnly)
9421 { # support for old ABI dumps
9422 if(not checkDump(1, "2.17")
9423 or not checkDump(2, "2.17"))
9424 {
9425 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9426 {
9427 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9428 {
9429 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9430 {
9431 $MnglName = $ShortName;
9432 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9433 }
9434 }
9435 }
9436 }
9437 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009438 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009439 { # support for old ABI dumps: some symbols are not mangled in old dumps
9440 # mangle both sets of symbols (old and new)
9441 # NOTE: remangling all symbols by the same mangler
9442 if($MnglName=~/\A_ZN(V|)K/)
9443 { # mangling may be incorrect on old ABI dumps
9444 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009445 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009446 }
9447 if($MnglName=~/\A_ZN(K|)V/)
9448 { # mangling may be incorrect on old ABI dumps
9449 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009450 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009452 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9453 or (not $ClassID and $CheckHeadersOnly)
9454 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9455 { # support for old ABI dumps, GCC >= 4.0
9456 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009457 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009458 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009459 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009460 $MangledNames{$LibVersion}{$MnglName} = 1;
9461 }
9462 }
9463 }
9464 elsif($Remangle==-1)
9465 { # remove mangling
9466 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009467 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009469 if(not $MnglName) {
9470 next;
9471 }
9472 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9473 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009474 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009477 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 { # support for old dumps
9479 # add "Volatile" attribute
9480 if($MnglName=~/_Z(K|)V/) {
9481 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9482 }
9483 }
9484 # symbol and its symlink have same signatures
9485 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009486 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009487 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009488
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009489 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9490 {
9491 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9492 if($SymVer{$LibVersion}{$Alias}) {
9493 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9494 }
9495 }
9496
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009497 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009498 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009499 }
9500 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9501 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9502 }
9503 if($ExtendedCheck)
9504 { # --ext option
9505 addExtension($LibVersion);
9506 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009507
9508 # clean memory
9509 delete($SymbolInfo{$LibVersion});
9510
9511 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009512 { # detect allocable classes with public exported constructors
9513 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009514 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009515 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009516 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009517 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009518 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9519 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009520 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009521 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009522 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009523 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009524 $AllocableClass{$LibVersion}{$ClassName} = 1;
9525 }
9526 }
9527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009528 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009529 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009530 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009531 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009532 if($CheckHeadersOnly)
9533 {
9534 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9535 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9536 { # all symbols except non-virtual inline
9537 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9538 }
9539 }
9540 else {
9541 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009542 }
9543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009544 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009545 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009546 }
9547 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009548 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009549 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009550 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009551 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009552 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009553 if(defined $Base{"Type"}
9554 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009556 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009557 if($Name=~/<([^<>\s]+)>/)
9558 {
9559 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9560 $ReturnedClass{$LibVersion}{$Tid} = 1;
9561 }
9562 }
9563 else {
9564 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9565 }
9566 }
9567 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009568 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009569 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009570 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009571 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009572 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009573 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009574 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009575 if($Base{"Type"}=~/Struct|Class/)
9576 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009577 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009578 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9579 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009580 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009582 }
9583 }
9584 }
9585 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009586
9587 # mapping {short name => symbols}
9588 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009589 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009590 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009591 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009592 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009593 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009594 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009595 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009596 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9597 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009598 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009599 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009600 }
9601 }
9602 }
9603 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009604
9605 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009606 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009607 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009608 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009609 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009610 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9611 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009612 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009613 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009614 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009615 $ClassNames{$LibVersion}{$TName} = 1;
9616 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009617 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009618 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9619 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009620 }
9621 }
9622 }
9623 }
9624 }
9625}
9626
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009627sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009628{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009629 my ($Tid, $LibVersion) = @_;
9630 if(not $Tid) {
9631 return $Tid;
9632 }
9633
9634 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9635 {
9636 if($TName_Tid{$LibVersion}{$Name}) {
9637 return $TName_Tid{$LibVersion}{$Name};
9638 }
9639 }
9640
9641 return $Tid;
9642}
9643
9644sub register_SymbolUsage($$$)
9645{
9646 my ($InfoId, $UsedType, $LibVersion) = @_;
9647
9648 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9649 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9650 {
9651 register_TypeUsage($RTid, $UsedType, $LibVersion);
9652 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9653 }
9654 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9655 {
9656 register_TypeUsage($FCid, $UsedType, $LibVersion);
9657 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9658
9659 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9660 { # register "this" pointer
9661 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9662 }
9663 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9664 { # register "this" pointer (const method)
9665 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9666 }
9667 }
9668 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9669 {
9670 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9671 {
9672 register_TypeUsage($PTid, $UsedType, $LibVersion);
9673 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9674 }
9675 }
9676 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9677 {
9678 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9679 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9680 register_TypeUsage($TTid, $UsedType, $LibVersion);
9681 }
9682 }
9683}
9684
9685sub register_TypeUsage($$$)
9686{
9687 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009688 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009689 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009690 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009691 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009692 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009693 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009694 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009695
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009696 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009697 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009698 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009699 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009700 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009701 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9702 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9703 }
9704 }
9705
9706 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9707 {
9708 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009709 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009710 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009711 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9712 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009713 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9715 {
9716 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9717 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009718 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009719 }
9720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009721 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009722 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009723 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009724 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9725 {
9726 register_TypeUsage($MTid, $UsedType, $LibVersion);
9727 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009728 }
9729 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009730 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009731 or $TInfo{"Type"} eq "MethodPtr"
9732 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009733 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009734 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009735 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009736 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009737 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009738 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009739 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9740 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009741 }
9742 }
9743 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009744 if($TInfo{"Type"} eq "FieldPtr")
9745 {
9746 if(my $RTid = $TInfo{"Return"}) {
9747 register_TypeUsage($RTid, $UsedType, $LibVersion);
9748 }
9749 if(my $CTid = $TInfo{"Class"}) {
9750 register_TypeUsage($CTid, $UsedType, $LibVersion);
9751 }
9752 }
9753 if($TInfo{"Type"} eq "MethodPtr")
9754 {
9755 if(my $CTid = $TInfo{"Class"}) {
9756 register_TypeUsage($CTid, $UsedType, $LibVersion);
9757 }
9758 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009759 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009760 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009761 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009762 $UsedType->{$TypeId} = 1;
9763 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9764 {
9765 register_TypeUsage($BTid, $UsedType, $LibVersion);
9766 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9767 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009768 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009769 else
9770 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9771 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009772 }
9773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009774}
9775
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009776sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009777{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009778 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9779
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009780 if($Level eq "Dump")
9781 {
9782 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9783 { # TODO: check if this symbol is from
9784 # base classes of other target symbols
9785 return 1;
9786 }
9787 }
9788
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009789 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9790 { # stdc++ interfaces
9791 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009792 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009793
9794 my $Target = 0;
9795 if(my $Header = $SInfo->{"Header"}) {
9796 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9797 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009798 if($ExtendedCheck)
9799 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009800 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009801 $Target = 1;
9802 }
9803 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009804 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009805 {
9806 if($Target)
9807 {
9808 if($Level eq "Dump")
9809 { # dumped
9810 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009811 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009812 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009813 return 1;
9814 }
9815 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009816 else {
9817 return 1;
9818 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009819 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009820 elsif($Level eq "Source")
9821 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009822 return 1;
9823 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009824 elsif($Level eq "Binary")
9825 { # checked
9826 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9827 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9828 return 1;
9829 }
9830 }
9831 }
9832 }
9833 else
9834 { # library is available
9835 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9836 { # exported symbols
9837 return 1;
9838 }
9839 if($Level eq "Dump")
9840 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009841 if($BinaryOnly)
9842 {
9843 if($SInfo->{"Data"})
9844 {
9845 if($Target) {
9846 return 1;
9847 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009848 }
9849 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009850 else
9851 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009852 if($Target) {
9853 return 1;
9854 }
9855 }
9856 }
9857 elsif($Level eq "Source")
9858 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009859 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9860 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009861 { # skip LOCAL symbols
9862 if($Target) {
9863 return 1;
9864 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009865 }
9866 }
9867 elsif($Level eq "Binary")
9868 { # checked
9869 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9870 {
9871 if($Target) {
9872 return 1;
9873 }
9874 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009875 }
9876 }
9877 return 0;
9878}
9879
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009880sub cleanDump($)
9881{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009882 my $LibVersion = $_[0];
9883 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9884 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009885 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9886 {
9887 delete($SymbolInfo{$LibVersion}{$InfoId});
9888 next;
9889 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009890 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009891 if(not $MnglName)
9892 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009893 delete($SymbolInfo{$LibVersion}{$InfoId});
9894 next;
9895 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009896 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009897 if(not $ShortName)
9898 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009899 delete($SymbolInfo{$LibVersion}{$InfoId});
9900 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009901 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009902 if($MnglName eq $ShortName)
9903 { # remove duplicate data
9904 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009905 }
9906 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9907 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9908 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009909 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9910 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9911 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009912 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009913 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009914 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009915 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009916 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9917 {
9918 delete($TypeInfo{$LibVersion}{$Tid});
9919 next;
9920 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009921 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009922 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009923 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009924 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9925 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9926 }
9927 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009928 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9929 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009931 }
9932}
9933
9934sub selectType($$)
9935{
9936 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009937
9938 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9939 {
9940 if(defined $TypeInfo{$LibVersion}{$Dupl})
9941 {
9942 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9943 { # duplicate
9944 return 0;
9945 }
9946 }
9947 }
9948
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009949 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9950 {
9951 if(not isBuiltIn($THeader))
9952 {
9953 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009954 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009955 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9956 {
9957 if(is_target_header($THeader, $LibVersion))
9958 { # from target headers
9959 if(not selfTypedef($Tid, $LibVersion)) {
9960 return 1;
9961 }
9962 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009963 }
9964 }
9965 }
9966 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009967 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009968}
9969
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009970sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009971{ # remove unused data types from the ABI dump
9972 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009973
9974 my %UsedType = ();
9975
9976 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009977 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009978 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009979 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009980 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009981 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009982 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009983 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009984 next;
9985 }
9986
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009987 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009988 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009989 if(selectType($Tid, $LibVersion))
9990 {
9991 my %Tree = ();
9992 register_TypeUsage($Tid, \%Tree, $LibVersion);
9993
9994 my $Tmpl = 0;
9995 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9996 {
9997 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9998 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9999 {
10000 $Tmpl = 1;
10001 last;
10002 }
10003 }
10004 if(not $Tmpl)
10005 {
10006 foreach (keys(%Tree)) {
10007 $UsedType{$_} = 1;
10008 }
10009 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010010 }
10011 }
10012 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010013
10014 my %Delete = ();
10015
10016 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010017 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010018 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010019 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010020 next;
10021 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010022
10023 if($Kind eq "Extra")
10024 {
10025 my %Tree = ();
10026 register_TypeUsage($Tid, \%Tree, $LibVersion);
10027
10028 foreach (sort {int($a)<=>int($b)} keys(%Tree))
10029 {
10030 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
10031 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10032 {
10033 $Delete{$Tid} = 1;
10034 last;
10035 }
10036 }
10037 }
10038 else
10039 {
10040 # remove type
10041 delete($TypeInfo{$LibVersion}{$Tid});
10042 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010043 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010044
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010045 if($Kind eq "Extra")
10046 { # remove duplicates
10047 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10048 {
10049 if($UsedType{$Tid})
10050 { # All & Extended
10051 next;
10052 }
10053
10054 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10055
10056 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10057 delete($TypeInfo{$LibVersion}{$Tid});
10058 }
10059 }
10060 }
10061
10062 foreach my $Tid (keys(%Delete))
10063 {
10064 delete($TypeInfo{$LibVersion}{$Tid});
10065 }
10066}
10067
10068sub check_Completeness($$)
10069{
10070 my ($Info, $LibVersion) = @_;
10071
10072 # data types
10073 if(defined $Info->{"Memb"})
10074 {
10075 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10076 {
10077 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10078 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10079 }
10080 }
10081 }
10082 if(defined $Info->{"Base"})
10083 {
10084 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10085 check_TypeInfo($Bid, $LibVersion);
10086 }
10087 }
10088 if(defined $Info->{"BaseType"}) {
10089 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10090 }
10091 if(defined $Info->{"TParam"})
10092 {
10093 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10094 {
10095 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10096 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10097 next;
10098 }
10099 if($TName eq "_BoolType") {
10100 next;
10101 }
10102 if($TName=~/\Asizeof\(/) {
10103 next;
10104 }
10105 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10106 check_TypeInfo($Tid, $LibVersion);
10107 }
10108 else
10109 {
10110 if(defined $Debug) {
10111 printMsg("WARNING", "missed type $TName");
10112 }
10113 }
10114 }
10115 }
10116
10117 # symbols
10118 if(defined $Info->{"Param"})
10119 {
10120 foreach my $Pos (keys(%{$Info->{"Param"}}))
10121 {
10122 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10123 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10124 }
10125 }
10126 }
10127 if(defined $Info->{"Return"}) {
10128 check_TypeInfo($Info->{"Return"}, $LibVersion);
10129 }
10130 if(defined $Info->{"Class"}) {
10131 check_TypeInfo($Info->{"Class"}, $LibVersion);
10132 }
10133}
10134
10135sub check_TypeInfo($$)
10136{
10137 my ($Tid, $LibVersion) = @_;
10138
10139 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10140 return;
10141 }
10142 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10143
10144 if(defined $TypeInfo{$LibVersion}{$Tid})
10145 {
10146 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10147 printMsg("ERROR", "missed type name ($Tid)");
10148 }
10149 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10150 }
10151 else {
10152 printMsg("ERROR", "missed type id $Tid");
10153 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010154}
10155
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010156sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010157{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010158 my ($TypeId, $LibVersion) = @_;
10159 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010160 if($Type{"Type"} eq "Typedef")
10161 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010162 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010163 if($Base{"Type"}=~/Class|Struct/)
10164 {
10165 if($Type{"Name"} eq $Base{"Name"}) {
10166 return 1;
10167 }
10168 elsif($Type{"Name"}=~/::(\w+)\Z/)
10169 {
10170 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10171 { # QPointer<QWidget>::QPointer
10172 return 1;
10173 }
10174 }
10175 }
10176 }
10177 return 0;
10178}
10179
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010180sub addExtension($)
10181{
10182 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010183 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010184 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010185 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010186 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010187 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10188 $TName=~s/\A(struct|union|class|enum) //;
10189 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010190
10191 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10192 "Header" => "extended.h",
10193 "ShortName" => $Symbol,
10194 "MnglName" => $Symbol,
10195 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10196 );
10197
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010198 $ExtendedSymbols{$Symbol} = 1;
10199 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10200 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010201 }
10202 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010203 $ExtendedSymbols{"external_func_0"} = 1;
10204 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10205 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010206}
10207
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010208sub findMethod($$$)
10209{
10210 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010211 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010212 {
10213 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10214 return $VirtMethodInClass;
10215 }
10216 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10217 return $VirtMethodInBaseClasses;
10218 }
10219 }
10220 return "";
10221}
10222
10223sub findMethod_Class($$$)
10224{
10225 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010226 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010227 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10228 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10229 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10230 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10231 { # search for interface with the same parameters suffix (overridden)
10232 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10233 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010234 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10235 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010236 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10237 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010238 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10239 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10240 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10241 return $Candidate;
10242 }
10243 }
10244 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010245 else
10246 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010247 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10248 return $Candidate;
10249 }
10250 }
10251 }
10252 }
10253 return "";
10254}
10255
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010256sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010257{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010258 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010259 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010261 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10262 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010263 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010264 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010265 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010266 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10267 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010268 { # pure virtual D2-destructors are marked as "virt" in the dump
10269 # virtual D2-destructors are NOT marked as "virt" in the dump
10270 # both destructors are not presented in the v-table
10271 next;
10272 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010273 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010274 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010276 }
10277}
10278
10279sub registerOverriding($)
10280{
10281 my $LibVersion = $_[0];
10282 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010283 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010284 foreach my $ClassName (@Classes)
10285 {
10286 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10287 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010288 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10289 { # pure virtuals
10290 next;
10291 }
10292 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10293 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010294 {
10295 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10296 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10297 { # both overridden virtual methods
10298 # and implemented pure virtual methods
10299 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10300 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10301 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010303 }
10304 }
10305 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10306 delete($VirtualTable{$LibVersion}{$ClassName});
10307 }
10308 }
10309}
10310
10311sub setVirtFuncPositions($)
10312{
10313 my $LibVersion = $_[0];
10314 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10315 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010316 my ($Num, $Rel) = (1, 0);
10317
10318 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010319 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010320 if($UsedDump{$LibVersion}{"DWARF"}) {
10321 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10322 }
10323 else {
10324 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10325 }
10326 foreach my $VirtFunc (@Funcs)
10327 {
10328 if($UsedDump{$LibVersion}{"DWARF"}) {
10329 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10330 }
10331 else {
10332 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10333 }
10334
10335 # set relative positions
10336 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10337 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10338 { # relative position excluding added and removed virtual functions
10339 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10340 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10341 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010345 }
10346 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010347 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010348 {
10349 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010350 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010351 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010352 }
10353 }
10354}
10355
10356sub get_sub_classes($$$)
10357{
10358 my ($ClassId, $LibVersion, $Recursive) = @_;
10359 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10360 my @Subs = ();
10361 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10362 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010363 if($Recursive)
10364 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010365 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10366 push(@Subs, $SubSubId);
10367 }
10368 }
10369 push(@Subs, $SubId);
10370 }
10371 return @Subs;
10372}
10373
10374sub get_base_classes($$$)
10375{
10376 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010377 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010378 return () if(not defined $ClassType{"Base"});
10379 my @Bases = ();
10380 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10381 keys(%{$ClassType{"Base"}}))
10382 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010383 if($Recursive)
10384 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010385 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10386 push(@Bases, $SubBaseId);
10387 }
10388 }
10389 push(@Bases, $BaseId);
10390 }
10391 return @Bases;
10392}
10393
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010394sub getVTable_Model($$)
10395{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010396 my ($ClassId, $LibVersion) = @_;
10397 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10398 my @Elements = ();
10399 foreach my $BaseId (@Bases, $ClassId)
10400 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010401 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010402 {
10403 if(defined $VirtualTable{$LibVersion}{$BName})
10404 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010405 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10406 if($UsedDump{$LibVersion}{"DWARF"}) {
10407 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10408 }
10409 else {
10410 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10411 }
10412 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010413 push(@Elements, $VFunc);
10414 }
10415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010416 }
10417 }
10418 return @Elements;
10419}
10420
10421sub getVShift($$)
10422{
10423 my ($ClassId, $LibVersion) = @_;
10424 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10425 my $VShift = 0;
10426 foreach my $BaseId (@Bases)
10427 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010428 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010429 {
10430 if(defined $VirtualTable{$LibVersion}{$BName}) {
10431 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010433 }
10434 }
10435 return $VShift;
10436}
10437
10438sub getShift($$)
10439{
10440 my ($ClassId, $LibVersion) = @_;
10441 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10442 my $Shift = 0;
10443 foreach my $BaseId (@Bases)
10444 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010445 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010446 {
10447 if($Size!=1)
10448 { # not empty base class
10449 $Shift+=$Size;
10450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010451 }
10452 }
10453 return $Shift;
10454}
10455
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010456sub getVTable_Size($$)
10457{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010458 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010459 my $Size = 0;
10460 # three approaches
10461 if(not $Size)
10462 { # real size
10463 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10464 $Size = keys(%VTable);
10465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010466 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010467 if(not $Size)
10468 { # shared library symbol size
10469 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10470 $Size /= $WORD_SIZE{$LibVersion};
10471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010473 if(not $Size)
10474 { # model size
10475 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10476 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10477 }
10478 }
10479 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010480}
10481
10482sub isCopyingClass($$)
10483{
10484 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010485 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010486}
10487
10488sub isLeafClass($$)
10489{
10490 my ($ClassId, $LibVersion) = @_;
10491 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10492}
10493
10494sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010495{ # check structured type for public fields
10496 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497}
10498
10499sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010500{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010501 my ($TypePtr, $Skip, $Start, $End) = @_;
10502 return 0 if(not $TypePtr);
10503 if($End==-1) {
10504 $End = keys(%{$TypePtr->{"Memb"}})-1;
10505 }
10506 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10507 {
10508 if($Skip and $Skip->{$MemPos})
10509 { # skip removed/added fields
10510 next;
10511 }
10512 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10513 {
10514 if(isPublic($TypePtr, $MemPos)) {
10515 return ($MemPos+1);
10516 }
10517 }
10518 }
10519 return 0;
10520}
10521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010522sub isReserved($)
10523{ # reserved fields == private
10524 my $MName = $_[0];
10525 if($MName=~/reserved|padding|f_spare/i) {
10526 return 1;
10527 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010528 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 return 1;
10530 }
10531 if($MName=~/(pad\d+)/i) {
10532 return 1;
10533 }
10534 return 0;
10535}
10536
10537sub isPublic($$)
10538{
10539 my ($TypePtr, $FieldPos) = @_;
10540 return 0 if(not $TypePtr);
10541 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10542 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10543 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10544 { # by name in C language
10545 # FIXME: add other methods to detect private members
10546 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10547 if($MName=~/priv|abidata|parent_object/i)
10548 { # C-styled private data
10549 return 0;
10550 }
10551 if(lc($MName) eq "abi")
10552 { # ABI information/reserved field
10553 return 0;
10554 }
10555 if(isReserved($MName))
10556 { # reserved fields
10557 return 0;
10558 }
10559 return 1;
10560 }
10561 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10562 { # by access in C++ language
10563 return 1;
10564 }
10565 return 0;
10566}
10567
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010568sub getVTable_Real($$)
10569{
10570 my ($ClassName, $LibVersion) = @_;
10571 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10572 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010573 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010574 if(defined $Type{"VTable"}) {
10575 return %{$Type{"VTable"}};
10576 }
10577 }
10578 return ();
10579}
10580
10581sub cmpVTables($)
10582{
10583 my $ClassName = $_[0];
10584 my $Res = cmpVTables_Real($ClassName, 1);
10585 if($Res==-1) {
10586 $Res = cmpVTables_Model($ClassName);
10587 }
10588 return $Res;
10589}
10590
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591sub cmpVTables_Model($)
10592{
10593 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010594 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010595 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010596 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010597 return 1;
10598 }
10599 }
10600 return 0;
10601}
10602
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010603sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010604{
10605 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010606 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10607 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010608 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 my %VTable_Old = getVTable_Real($ClassName, 1);
10610 my %VTable_New = getVTable_Real($ClassName, 2);
10611 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010612 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010613 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010614 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010615 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010616 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10617 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010618 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010619 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010620 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010621 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010622 my $Entry1 = $VTable_Old{$Offset};
10623 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010624 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010625 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010626 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010627 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010628 $Entry1 = simpleVEntry($Entry1);
10629 $Entry2 = simpleVEntry($Entry2);
10630 if($Entry1 ne $Entry2)
10631 { # register as changed
10632 if($Entry1=~/::([^:]+)\Z/)
10633 {
10634 my $M1 = $1;
10635 if($Entry2=~/::([^:]+)\Z/)
10636 {
10637 my $M2 = $1;
10638 if($M1 eq $M2)
10639 { # overridden
10640 next;
10641 }
10642 }
10643 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010644 if(differentDumps("G"))
10645 {
10646 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10647 {
10648 # GCC 4.6.1: -0x00000000000000010
10649 # GCC 4.7.0: -16
10650 next;
10651 }
10652 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010653 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010654 }
10655 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010656 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657}
10658
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010659sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010660{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010661 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010662 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10663 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010664 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010665 { # already registered
10666 next;
10667 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010668 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010670 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010671 foreach my $Symbol (@Affected)
10672 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010673 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010674 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010675 "Target"=>$ClassName);
10676 }
10677 }
10678 }
10679}
10680
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010681sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010682{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010683 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010684 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010685 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010686 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010687 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010688 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010689 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010690 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010691 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010692 if($TName_Tid{1}{$ClassName}
10693 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010694 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010695 if(defined $CompleteSignature{1}{$Symbol}
10696 and $CompleteSignature{1}{$Symbol}{"Virt"})
10697 { # override some method in v.1
10698 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010699 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010700 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010701 }
10702 }
10703 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010704 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010705 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010706 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010707 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010708 if($TName_Tid{2}{$ClassName}
10709 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010710 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010711 if(defined $CompleteSignature{2}{$Symbol}
10712 and $CompleteSignature{2}{$Symbol}{"Virt"})
10713 { # override some method in v.2
10714 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010715 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010716 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010717 }
10718 }
10719 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010720 if($Level eq "Binary")
10721 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010722 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010723 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10724 { # check replacements, including pure virtual methods
10725 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10726 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010727 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010728 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10729 if($AddedPos==$RemovedPos)
10730 {
10731 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10732 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10733 last; # other methods will be reported as "added" or "removed"
10734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010736 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10737 {
10738 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10739 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010740 next;
10741 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010742 my $ProblemType = "Virtual_Replacement";
10743 my @Affected = ($RemovedVFunc);
10744 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10745 { # pure methods
10746 if(not isUsedClass($ClassId, 1, $Level))
10747 { # not a parameter of some exported method
10748 next;
10749 }
10750 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010751
10752 # affected all methods (both virtual and non-virtual ones)
10753 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10754 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010755 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010756 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010757 foreach my $AffectedInt (@Affected)
10758 {
10759 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10760 { # affected exported methods only
10761 next;
10762 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010763 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10764 next;
10765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010766 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10767 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010768 "Target"=>get_Signature($AddedVFunc, 2),
10769 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010771 }
10772 }
10773 }
10774 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010775 if(not checkDump(1, "2.0")
10776 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010777 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010778 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010779 return;
10780 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010781 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010782 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010783 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010784 next if(not $ClassId_Old);
10785 if(not isCreatable($ClassId_Old, 1))
10786 { # skip classes without public constructors (including auto-generated)
10787 # example: class has only a private exported or private inline constructor
10788 next;
10789 }
10790 if($ClassName=~/>/)
10791 { # skip affected template instances
10792 next;
10793 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010794 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010795 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010796 if(not $ClassId_New) {
10797 next;
10798 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010799 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010800 if($Class_New{"Type"}!~/Class|Struct/)
10801 { # became typedef
10802 if($Level eq "Binary") {
10803 next;
10804 }
10805 if($Level eq "Source")
10806 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010807 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010808 if($Class_New{"Type"}!~/Class|Struct/) {
10809 next;
10810 }
10811 $ClassId_New = $Class_New{"Tid"};
10812 }
10813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010814 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10815 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 +040010816
10817 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10818 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10819
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010820 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010821 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10822 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010823 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10824 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010825 my $Shift_Old = getShift($ClassId_Old, 1);
10826 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010827 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010828 my ($Added, $Removed) = (0, 0);
10829 my @StableBases_Old = ();
10830 foreach my $BaseId (@Bases_Old)
10831 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010832 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010833 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 push(@StableBases_Old, $BaseId);
10835 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010836 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010837 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010838 { # removed base
10839 # excluding namespace::SomeClass to SomeClass renaming
10840 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010841 if($Level eq "Binary")
10842 { # Binary-level
10843 if($Shift_Old ne $Shift_New)
10844 { # affected fields
10845 if(havePubFields(\%Class_Old)) {
10846 $ProblemKind .= "_And_Shift";
10847 }
10848 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10849 $ProblemKind .= "_And_Size";
10850 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010851 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010852 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10853 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010854 { # affected v-table
10855 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010856 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010857 }
10858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010859 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010860 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10861 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010862 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10863 {
10864 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10865 if($ProblemKind=~/VTable/) {
10866 $VTableChanged_M{$SubName}=1;
10867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010868 }
10869 }
10870 foreach my $Interface (@Affected)
10871 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010872 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10873 next;
10874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010876 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010877 "Target"=>$BaseName,
10878 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10879 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10880 "Shift"=>abs($Shift_New-$Shift_Old) );
10881 }
10882 $Removed+=1;
10883 }
10884 }
10885 my @StableBases_New = ();
10886 foreach my $BaseId (@Bases_New)
10887 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010888 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010889 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010890 push(@StableBases_New, $BaseId);
10891 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010892 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010893 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010894 { # added base
10895 # excluding namespace::SomeClass to SomeClass renaming
10896 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010897 if($Level eq "Binary")
10898 { # Binary-level
10899 if($Shift_Old ne $Shift_New)
10900 { # affected fields
10901 if(havePubFields(\%Class_Old)) {
10902 $ProblemKind .= "_And_Shift";
10903 }
10904 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10905 $ProblemKind .= "_And_Size";
10906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010907 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010908 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10909 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010910 { # affected v-table
10911 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010912 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010913 }
10914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010915 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010916 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10917 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010918 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10919 {
10920 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10921 if($ProblemKind=~/VTable/) {
10922 $VTableChanged_M{$SubName}=1;
10923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010924 }
10925 }
10926 foreach my $Interface (@Affected)
10927 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010928 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10929 next;
10930 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010931 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010932 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010933 "Target"=>$BaseName,
10934 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10935 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10936 "Shift"=>abs($Shift_New-$Shift_Old) );
10937 }
10938 $Added+=1;
10939 }
10940 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 if($Level eq "Binary")
10942 { # Binary-level
10943 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010944 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10945 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010946 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010947 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010948 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010949 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010950 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010951 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10952 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 if($NewPos!=$OldPos)
10954 { # changed position of the base class
10955 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010956 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010957 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10958 next;
10959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010960 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10961 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010962 "Target"=>$BaseName,
10963 "Old_Value"=>$OldPos-1,
10964 "New_Value"=>$NewPos-1 );
10965 }
10966 }
10967 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10968 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10969 { # became non-virtual base
10970 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10971 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010972 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10973 next;
10974 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010975 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10976 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010977 "Target"=>$BaseName );
10978 }
10979 }
10980 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10981 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10982 { # became virtual base
10983 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10984 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010985 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10986 next;
10987 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010988 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10989 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010990 "Target"=>$BaseName );
10991 }
10992 }
10993 }
10994 }
10995 # detect size changes in base classes
10996 if($Shift_Old!=$Shift_New)
10997 { # size of allocable class
10998 foreach my $BaseId (@StableBases_Old)
10999 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011000 my %BaseType = get_Type($BaseId, 1);
11001 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011002 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011003 if($Size_Old ne $Size_New
11004 and $Size_Old and $Size_New)
11005 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011006 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007 if(isCopyingClass($BaseId, 1)) {
11008 $ProblemType = "Size_Of_Copying_Class";
11009 }
11010 elsif($AllocableClass{1}{$BaseType{"Name"}})
11011 {
11012 if($Size_New>$Size_Old)
11013 { # increased size
11014 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011015 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011016 else
11017 { # decreased size
11018 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11019 if(not havePubFields(\%Class_Old))
11020 { # affected class has no public members
11021 next;
11022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011023 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011024 }
11025 next if(not $ProblemType);
11026 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11027 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011028 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11029 next;
11030 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011031 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11032 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011033 "Target"=>$BaseType{"Name"},
11034 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11035 "New_Size"=>$Size_New*$BYTE_SIZE );
11036 }
11037 }
11038 }
11039 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011040 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011041 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011042 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011043 { # compare virtual tables size in base classes
11044 my $VShift_Old = getVShift($ClassId_Old, 1);
11045 my $VShift_New = getVShift($ClassId_New, 2);
11046 if($VShift_Old ne $VShift_New)
11047 { # changes in the base class or changes in the list of base classes
11048 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11049 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11050 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011051 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011052 foreach my $BaseId (@AllBases_Old)
11053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011054 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011055 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011056 { # lost base
11057 next;
11058 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011059 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11060 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011061 if($VSize_Old!=$VSize_New)
11062 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011063 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011064 { # TODO: affected non-virtual methods?
11065 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011066 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11067 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011068 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011069 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 { # skip interfaces that have not changed the absolute virtual position
11071 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011073 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11074 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011075 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011076 $VTableChanged_M{$BaseType{"Name"}} = 1;
11077 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011078 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11079 { # the reason of the layout change: added virtual functions
11080 next if($VirtualReplacement{$VirtFunc});
11081 my $ProblemType = "Added_Virtual_Method";
11082 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11083 $ProblemType = "Added_Pure_Virtual_Method";
11084 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011085 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011087 "Target"=>get_Signature($VirtFunc, 2) );
11088 }
11089 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11090 { # the reason of the layout change: removed virtual functions
11091 next if($VirtualReplacement{$VirtFunc});
11092 my $ProblemType = "Removed_Virtual_Method";
11093 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11094 $ProblemType = "Removed_Pure_Virtual_Method";
11095 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011096 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011097 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011098 "Target"=>get_Signature($VirtFunc, 1) );
11099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011100 }
11101 }
11102 }
11103 }
11104 }
11105 }
11106 }
11107}
11108
11109sub isCreatable($$)
11110{
11111 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011112 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011113 or isCopyingClass($ClassId, $LibVersion)) {
11114 return 1;
11115 }
11116 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11117 { # Fix for incomplete data: if this class has
11118 # a base class then it should also has a constructor
11119 return 1;
11120 }
11121 if($ReturnedClass{$LibVersion}{$ClassId})
11122 { # returned by some method of this class
11123 # or any other class
11124 return 1;
11125 }
11126 return 0;
11127}
11128
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011130{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011131 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011132 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11133 { # parameter of some exported method
11134 return 1;
11135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011136 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11137 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011138 { # method from target class
11139 return 1;
11140 }
11141 return 0;
11142}
11143
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011144sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011145{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011146 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011147 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011148 # - virtual
11149 # - pure-virtual
11150 # - non-virtual
11151 if($CompleteSignature{1}{$Interface}{"Data"})
11152 { # global data is not affected
11153 return;
11154 }
11155 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011156 if(not $Class_Id) {
11157 return;
11158 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011159 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011160 if(cmpVTables_Real($CName, 1)==0)
11161 { # no changes
11162 return;
11163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011164 $CheckedTypes{$Level}{$CName} = 1;
11165 if($Level eq "Binary")
11166 { # Binary-level
11167 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11168 and not isUsedClass($Class_Id, 1, $Level))
11169 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011170 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011171 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011172 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011173 }
11174 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11175 {
11176 if(defined $VirtualTable{2}{$CName}{$Func}
11177 and defined $CompleteSignature{2}{$Func})
11178 {
11179 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11180 and $CompleteSignature{2}{$Func}{"PureVirt"})
11181 { # became pure virtual
11182 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11183 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011184 "Target"=>get_Signature_M($Func, 1) );
11185 $VTableChanged_M{$CName} = 1;
11186 }
11187 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11188 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11189 { # became non-pure virtual
11190 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11191 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011192 "Target"=>get_Signature_M($Func, 1) );
11193 $VTableChanged_M{$CName} = 1;
11194 }
11195 }
11196 }
11197 if($Level eq "Binary")
11198 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011199 # check virtual table structure
11200 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11201 {
11202 next if($Interface eq $AddedVFunc);
11203 next if($VirtualReplacement{$AddedVFunc});
11204 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11205 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11206 { # pure virtual methods affect all others (virtual and non-virtual)
11207 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011208 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011209 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011210 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011211 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011212 elsif(not defined $VirtualTable{1}{$CName}
11213 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011214 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011215 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 { # became polymorphous class, added v-table pointer
11217 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011219 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011220 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011221 }
11222 else
11223 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011224 my $VSize_Old = getVTable_Size($CName, 1);
11225 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011226 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011227 if(isCopyingClass($Class_Id, 1))
11228 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11229 my $ProblemType = "Added_Virtual_Method";
11230 if(isLeafClass($Class_Id, 1)) {
11231 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11232 }
11233 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11234 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011235 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011236 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011237 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011238 else
11239 {
11240 my $ProblemType = "Added_Virtual_Method";
11241 if(isLeafClass($Class_Id, 1)) {
11242 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11243 }
11244 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11245 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011246 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011247 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011249 }
11250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011251 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11252 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011253 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011254 if(defined $VirtualTable{1}{$CName}
11255 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011256 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011257 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11258 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011259
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011260 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011261 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011262 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11263 foreach my $ASymbol (@Affected)
11264 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011265 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11266 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011267 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011268 next;
11269 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011270 }
11271 $CheckedSymbols{$Level}{$ASymbol} = 1;
11272 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11273 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011274 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011275 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011278 }
11279 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011280 else {
11281 # safe
11282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011284 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11285 {
11286 next if($VirtualReplacement{$RemovedVFunc});
11287 if($RemovedVFunc eq $Interface
11288 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11289 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011290 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011291 next;
11292 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011293 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011294 { # became non-polymorphous class, removed v-table pointer
11295 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11296 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011297 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011298 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011299 }
11300 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11301 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11302 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011303 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011304 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011305 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11306 next;
11307 }
11308 my $VPos_New = -1;
11309 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011310 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011311 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11312 }
11313 else
11314 {
11315 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011316 next;
11317 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011318 }
11319 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11320 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11321 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11322 {
11323 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11324 foreach my $ASymbol (@Affected)
11325 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011326 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11327 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011328 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011329 next;
11330 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011331 }
11332 my $ProblemType = "Removed_Virtual_Method";
11333 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11334 $ProblemType = "Removed_Pure_Virtual_Method";
11335 }
11336 $CheckedSymbols{$Level}{$ASymbol} = 1;
11337 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11338 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011339 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011340 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011341 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011342 }
11343 }
11344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011345 }
11346 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011347 else
11348 { # Source-level
11349 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011350 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011351 next if($Interface eq $AddedVFunc);
11352 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011353 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011354 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11355 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011356 "Target"=>get_Signature($AddedVFunc, 2) );
11357 }
11358 }
11359 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11360 {
11361 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11362 {
11363 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11364 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011365 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011366 }
11367 }
11368 }
11369}
11370
11371sub find_MemberPair_Pos_byName($$)
11372{
11373 my ($Member_Name, $Pair_Type) = @_;
11374 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11375 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11376 {
11377 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11378 {
11379 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11380 $Name=~s/\A[_]+|[_]+\Z//g;
11381 if($Name eq $Member_Name) {
11382 return $MemberPair_Pos;
11383 }
11384 }
11385 }
11386 return "lost";
11387}
11388
11389sub find_MemberPair_Pos_byVal($$)
11390{
11391 my ($Member_Value, $Pair_Type) = @_;
11392 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11393 {
11394 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11395 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11396 return $MemberPair_Pos;
11397 }
11398 }
11399 return "lost";
11400}
11401
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011402sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011403{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011404 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011405 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011406 if( $_->{"T1"} eq $_[0]
11407 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011408 {
11409 return 1;
11410 }
11411 }
11412 return 0;
11413}
11414
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011415sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011416{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011417 my %IDs = (
11418 "T1" => $_[0],
11419 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011420 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011421 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011422}
11423
11424sub isRenamed($$$$$)
11425{
11426 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11427 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11428 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011429 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011430 if(not defined $Type2->{"Memb"}{$MemPos}) {
11431 return "";
11432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011433 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011434 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011435
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011436 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11437 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011438 if($MemberPair_Pos_Rev eq "lost")
11439 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011440 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11441 { # base type match
11442 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011443 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011444 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11445 { # exact type match
11446 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011447 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011448 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11449 { # size match
11450 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011451 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011452 if(isReserved($Pair_Name))
11453 { # reserved fields
11454 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011455 }
11456 }
11457 return "";
11458}
11459
11460sub isLastElem($$)
11461{
11462 my ($Pos, $TypeRef) = @_;
11463 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11464 if($Name=~/last|count|max|total/i)
11465 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11466 return 1;
11467 }
11468 elsif($Name=~/END|NLIMITS\Z/)
11469 { # __RLIMIT_NLIMITS
11470 return 1;
11471 }
11472 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11473 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11474 { # NImageFormats, NColorRoles
11475 return 1;
11476 }
11477 return 0;
11478}
11479
11480sub nonComparable($$)
11481{
11482 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011483
11484 my $N1 = $T1->{"Name"};
11485 my $N2 = $T2->{"Name"};
11486
11487 $N1=~s/\A(struct|union|enum) //;
11488 $N2=~s/\A(struct|union|enum) //;
11489
11490 if($N1 ne $N2
11491 and not isAnon($N1)
11492 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011493 { # different names
11494 if($T1->{"Type"} ne "Pointer"
11495 or $T2->{"Type"} ne "Pointer")
11496 { # compare base types
11497 return 1;
11498 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011499 if($N1!~/\Avoid\s*\*/
11500 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011501 {
11502 return 1;
11503 }
11504 }
11505 elsif($T1->{"Type"} ne $T2->{"Type"})
11506 { # different types
11507 if($T1->{"Type"} eq "Class"
11508 and $T2->{"Type"} eq "Struct")
11509 { # "class" to "struct"
11510 return 0;
11511 }
11512 elsif($T2->{"Type"} eq "Class"
11513 and $T1->{"Type"} eq "Struct")
11514 { # "struct" to "class"
11515 return 0;
11516 }
11517 else
11518 { # "class" to "enum"
11519 # "union" to "class"
11520 # ...
11521 return 1;
11522 }
11523 }
11524 return 0;
11525}
11526
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011527sub isOpaque($)
11528{
11529 my $T = $_[0];
11530 if(not defined $T->{"Memb"})
11531 {
11532 return 1;
11533 }
11534 return 0;
11535}
11536
11537sub removeVPtr($)
11538{ # support for old ABI dumps
11539 my $TPtr = $_[0];
11540 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11541 if($#Pos>=1)
11542 {
11543 foreach my $Pos (0 .. $#Pos-1)
11544 {
11545 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11546 }
11547 delete($TPtr->{"Memb"}{$#Pos});
11548 }
11549}
11550
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011551sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011552{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011553 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011554 return {} if(not $Type1_Id or not $Type2_Id);
11555
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011556 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011557 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011558 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011559 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011560
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011561 my %Type1 = get_Type($Type1_Id, 1);
11562 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011563 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011564 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011565 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011566
11567 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011568 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11569 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011570
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011571 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11572
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011573 my %SubProblems = ();
11574
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011575 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11576 {
11577 if($Type1_Pure{"Type"}=~/Struct|Union/
11578 and $Type2_Pure{"Type"}=~/Struct|Union/)
11579 {
11580 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11581 {
11582 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11583 "Target"=>$Type1_Pure{"Name"},
11584 "Type_Name"=>$Type1_Pure{"Name"} );
11585
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011586 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011587 }
11588 }
11589 }
11590
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011591 if(not $Type1_Pure{"Size"}
11592 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011593 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011594 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11595 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11596 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011597 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011598 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011599 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011600 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011601 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011602 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011603 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011604 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11605 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11606 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011607
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011608 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11609 { # support for old ABI dumps
11610 # _vptr field added in 3.0
11611 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11612 {
11613 if(defined $Type2_Pure{"Memb"}
11614 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11615 {
11616 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11617 delete($Type2_Pure{"Memb"}{0});
11618 }
11619 else {
11620 removeVPtr(\%Type2_Pure);
11621 }
11622 }
11623 }
11624 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11625 {
11626 if(defined $Type1_Pure{"Memb"}
11627 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11628 {
11629 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11630 delete($Type1_Pure{"Memb"}{0});
11631 }
11632 else {
11633 removeVPtr(\%Type1_Pure);
11634 }
11635 }
11636 }
11637 }
11638
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011639 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11640 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011641
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011642 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11643 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11644 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011646 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11647 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011648 if($Base_1{"Name"} ne $Base_2{"Name"})
11649 {
11650 if(differentDumps("G")
11651 or differentDumps("V"))
11652 { # different GCC versions or different dumps
11653 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11654 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11655 # std::__va_list and __va_list
11656 $Base_1{"Name"}=~s/\A(\w+::)+//;
11657 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011658 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11659 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011661 }
11662 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11663 and $Base_1{"Name"} ne $Base_2{"Name"})
11664 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011665 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011666 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011667 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011668 {
11669 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11670 "Target"=>$Typedef_1{"Name"},
11671 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011672 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11673 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11674 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011675 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11676 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011677 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011678 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011679 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11680 {
11681 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11682 "Target"=>$Typedef_1{"Name"},
11683 "Type_Name"=>$Typedef_1{"Name"},
11684 "Old_Value"=>$Base_1{"Name"},
11685 "New_Value"=>$Base_2{"Name"} );
11686 }
11687 else
11688 {
11689 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11690 "Target"=>$Typedef_1{"Name"},
11691 "Type_Name"=>$Typedef_1{"Name"},
11692 "Old_Value"=>$Base_1{"Name"},
11693 "New_Value"=>$Base_2{"Name"} );
11694 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011696 }
11697 }
11698 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11699 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011700 my $TT1 = $Type1_Pure{"Type"};
11701 my $TT2 = $Type2_Pure{"Type"};
11702
11703 if($TT1 ne $TT2
11704 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011705 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011706 my $Short1 = $Type1_Pure{"Name"};
11707 my $Short2 = $Type2_Pure{"Name"};
11708
11709 $Short1=~s/\A\Q$TT1\E //ig;
11710 $Short2=~s/\A\Q$TT2\E //ig;
11711
11712 if($Short1 eq $Short2)
11713 {
11714 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11715 "Target"=>$Type1_Pure{"Name"},
11716 "Type_Name"=>$Type1_Pure{"Name"},
11717 "Old_Value"=>lc($Type1_Pure{"Type"}),
11718 "New_Value"=>lc($Type2_Pure{"Type"}) );
11719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011720 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011721 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011722 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011723 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011724 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11725 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11726 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11727 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011728 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011729 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011730 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011731 {
11732 my $ProblemKind = "DataType_Size";
11733 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011734 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011735 {
11736 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11737 $ProblemKind = "Size_Of_Copying_Class";
11738 }
11739 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11740 {
11741 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11742 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11743 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011744 else
11745 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011746 # descreased size of allocable class
11747 # it has no special effects
11748 }
11749 }
11750 }
11751 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11752 "Target"=>$Type1_Pure{"Name"},
11753 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011755 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011756 }
11757 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011758 if(defined $Type1_Pure{"BaseType"}
11759 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011760 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011761 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11762 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011763 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011764 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11765 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 }
11767 }
11768 }
11769 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11770 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11771 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11772 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11773 { # detect removed and renamed fields
11774 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11775 next if(not $Member_Name);
11776 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);
11777 if($MemberPair_Pos eq "lost")
11778 {
11779 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11780 {
11781 if(isUnnamed($Member_Name))
11782 { # support for old-version dumps
11783 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011784 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011785 next;
11786 }
11787 }
11788 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11789 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011790 $RenamedField{$Member_Pos} = $RenamedTo;
11791 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011792 }
11793 else
11794 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011795 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011796 }
11797 }
11798 elsif($Type1_Pure{"Type"} eq "Enum")
11799 {
11800 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11801 next if($Member_Value1 eq "");
11802 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11803 if($MemberPair_Pos ne "lost")
11804 { # renamed
11805 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11806 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11807 if($MemberPair_Pos_Rev eq "lost")
11808 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011809 $RenamedField{$Member_Pos} = $RenamedTo;
11810 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011811 }
11812 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011813 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011814 }
11815 }
11816 else
11817 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011818 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011819 }
11820 }
11821 }
11822 else
11823 { # related
11824 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11825 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11826 }
11827 }
11828 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11829 { # detect added fields
11830 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11831 next if(not $Member_Name);
11832 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);
11833 if($MemberPair_Pos eq "lost")
11834 {
11835 if(isUnnamed($Member_Name))
11836 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011837 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011838 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011839 next;
11840 }
11841 }
11842 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11843 {
11844 if(not $RenamedField_Rev{$Member_Pos})
11845 { # added
11846 $AddedField{$Member_Pos}=1;
11847 }
11848 }
11849 }
11850 }
11851 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11852 { # detect moved fields
11853 my (%RelPos, %RelPosName, %AbsPos) = ();
11854 my $Pos = 0;
11855 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11856 { # relative positions in 1st version
11857 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11858 next if(not $Member_Name);
11859 if(not $RemovedField{$Member_Pos})
11860 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011861 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011862 $RelPosName{1}{$Pos} = $Member_Name;
11863 $AbsPos{1}{$Pos++} = $Member_Pos;
11864 }
11865 }
11866 $Pos = 0;
11867 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11868 { # relative positions in 2nd version
11869 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11870 next if(not $Member_Name);
11871 if(not $AddedField{$Member_Pos})
11872 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011873 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011874 $RelPosName{2}{$Pos} = $Member_Name;
11875 $AbsPos{2}{$Pos++} = $Member_Pos;
11876 }
11877 }
11878 foreach my $Member_Name (keys(%{$RelPos{1}}))
11879 {
11880 my $RPos1 = $RelPos{1}{$Member_Name};
11881 my $AbsPos1 = $NameToPosA{$Member_Name};
11882 my $Member_Name2 = $Member_Name;
11883 if(my $RenamedTo = $RenamedField{$AbsPos1})
11884 { # renamed
11885 $Member_Name2 = $RenamedTo;
11886 }
11887 my $RPos2 = $RelPos{2}{$Member_Name2};
11888 if($RPos2 ne "" and $RPos1 ne $RPos2)
11889 { # different relative positions
11890 my $AbsPos2 = $NameToPosB{$Member_Name2};
11891 if($AbsPos1 ne $AbsPos2)
11892 { # different absolute positions
11893 my $ProblemType = "Moved_Field";
11894 if(not isPublic(\%Type1_Pure, $AbsPos1))
11895 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011896 if($Level eq "Source") {
11897 next;
11898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011899 $ProblemType = "Moved_Private_Field";
11900 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011901 if($Level eq "Binary"
11902 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011903 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011904 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011905 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011906 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011907 if($MemSize1 ne $MemSize2) {
11908 $ProblemType .= "_And_Size";
11909 }
11910 }
11911 if($ProblemType eq "Moved_Private_Field") {
11912 next;
11913 }
11914 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11915 "Target"=>$Member_Name,
11916 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011917 "Old_Value"=>$RPos1,
11918 "New_Value"=>$RPos2 );
11919 }
11920 }
11921 }
11922 }
11923 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011924 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011925 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11926 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011927 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011928 if(my $RenamedTo = $RenamedField{$Member_Pos})
11929 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011930 if(defined $Constants{2}{$Member_Name})
11931 {
11932 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11933 { # define OLD NEW
11934 next; # Safe
11935 }
11936 }
11937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011938 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11939 {
11940 if(isPublic(\%Type1_Pure, $Member_Pos))
11941 {
11942 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11943 "Target"=>$Member_Name,
11944 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 "Old_Value"=>$Member_Name,
11946 "New_Value"=>$RenamedTo );
11947 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011948 elsif(isReserved($Member_Name))
11949 {
11950 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11951 "Target"=>$Member_Name,
11952 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011953 "Old_Value"=>$Member_Name,
11954 "New_Value"=>$RenamedTo );
11955 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011956 }
11957 elsif($Type1_Pure{"Type"} eq "Enum")
11958 {
11959 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11960 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11961 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011962 "Old_Value"=>$Member_Name,
11963 "New_Value"=>$RenamedTo );
11964 }
11965 }
11966 elsif($RemovedField{$Member_Pos})
11967 { # removed
11968 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11969 {
11970 my $ProblemType = "Removed_Field";
11971 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011972 or isUnnamed($Member_Name))
11973 {
11974 if($Level eq "Source") {
11975 next;
11976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011977 $ProblemType = "Removed_Private_Field";
11978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011979 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011980 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011981 {
11982 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11983 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011984 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 +040011985 { # changed offset
11986 $ProblemType .= "_And_Layout";
11987 }
11988 }
11989 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11990 { # affected size
11991 $ProblemType .= "_And_Size";
11992 }
11993 }
11994 if($ProblemType eq "Removed_Private_Field") {
11995 next;
11996 }
11997 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11998 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011999 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012000 }
12001 elsif($Type2_Pure{"Type"} eq "Union")
12002 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012003 if($Level eq "Binary"
12004 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012005 {
12006 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12007 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012008 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009 }
12010 else
12011 {
12012 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12013 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012014 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012015 }
12016 }
12017 elsif($Type1_Pure{"Type"} eq "Enum")
12018 {
12019 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12020 "Target"=>$Member_Name,
12021 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012022 "Old_Value"=>$Member_Name );
12023 }
12024 }
12025 else
12026 { # changed
12027 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12028 if($Type1_Pure{"Type"} eq "Enum")
12029 {
12030 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12031 next if($Member_Value1 eq "");
12032 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12033 next if($Member_Value2 eq "");
12034 if($Member_Value1 ne $Member_Value2)
12035 {
12036 my $ProblemType = "Enum_Member_Value";
12037 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12038 $ProblemType = "Enum_Last_Member_Value";
12039 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012040 if($SkipConstants{1}{$Member_Name}) {
12041 $ProblemType = "Enum_Private_Member_Value";
12042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012043 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12044 "Target"=>$Member_Name,
12045 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012046 "Old_Value"=>$Member_Value1,
12047 "New_Value"=>$Member_Value2 );
12048 }
12049 }
12050 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12051 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012052 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12053 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12054
12055 if($Access1 ne "private"
12056 and $Access2 eq "private")
12057 {
12058 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12059 "Target"=>$Member_Name,
12060 "Type_Name"=>$Type1_Pure{"Name"});
12061 }
12062 elsif($Access1 ne "protected"
12063 and $Access1 ne "private"
12064 and $Access2 eq "protected")
12065 {
12066 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12067 "Target"=>$Member_Name,
12068 "Type_Name"=>$Type1_Pure{"Name"});
12069 }
12070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012071 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12072 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012073 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12075 $SizeV1 = $BSize1;
12076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012077 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012078 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12079 $SizeV2 = $BSize2;
12080 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012081 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12082 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012083 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012084 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012085 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012086 {
12087 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12088 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12089 { # field size change (including anon-structures and unions)
12090 # - same types
12091 # - unnamed types
12092 # - bitfields
12093 my $ProblemType = "Field_Size";
12094 if(not isPublic(\%Type1_Pure, $Member_Pos)
12095 or isUnnamed($Member_Name))
12096 { # should not be accessed by applications, goes to "Low Severity"
12097 # example: "abidata" members in GStreamer types
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 if($ProblemType eq "Private_Field_Size")
12115 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012116 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012117 if($ProblemType eq "Field_Size")
12118 {
12119 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12120 { # Low severity
12121 $ProblemType = "Struct_Field_Size_Increased";
12122 }
12123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012124 if($ProblemType)
12125 { # register a problem
12126 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12127 "Target"=>$Member_Name,
12128 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012129 "Old_Size"=>$SizeV1,
12130 "New_Size"=>$SizeV2);
12131 }
12132 }
12133 }
12134 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12135 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12136 { # do NOT check bitfield type changes
12137 next;
12138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012139 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012140 {
12141 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12142 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12143 {
12144 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12145 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012146 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012147 }
12148 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12149 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12150 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012151 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012152 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012153 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012154 }
12155 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012156 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12157 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012158 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012159 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12160 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012161
12162 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012163 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012164 or $ProblemType eq "Field_Type_And_Size"
12165 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012166 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012167 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012168 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012169 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012170 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012171 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012172 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012173 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012174 }
12175 }
12176 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12177 {
12178 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012179 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012180 }
12181 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012182 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012183 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012184 }
12185 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12186 {
12187 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012188 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012189 }
12190 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012191 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012192 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012193 }
12194 }
12195 }
12196
12197 if($Level eq "Source")
12198 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012199 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012200 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012201 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12202 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012203
12204 if($ProblemType eq "Field_Type")
12205 {
12206 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012207 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012208 }
12209 }
12210 }
12211 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012212
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012213 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012214 {
12215 my $ProblemType_Init = $ProblemType;
12216 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012217 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012218 if(not isPublic(\%Type1_Pure, $Member_Pos)
12219 or isUnnamed($Member_Name)) {
12220 $ProblemType = "Private_".$ProblemType;
12221 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012222 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 +040012223 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012224 if($Type2_Pure{"Type"} ne "Union"
12225 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012226 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012227 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 +040012228 { # changed offset
12229 $ProblemType .= "_And_Layout";
12230 }
12231 }
12232 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12233 $ProblemType .= "_And_Type_Size";
12234 }
12235 }
12236 }
12237 else
12238 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012239 # TODO: Private_Field_Type rule?
12240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012241 if(not isPublic(\%Type1_Pure, $Member_Pos)
12242 or isUnnamed($Member_Name)) {
12243 next;
12244 }
12245 }
12246 if($ProblemType eq "Private_Field_Type_And_Size")
12247 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 }
12249 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12250 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012251 "Type_Name"=>$Type1_Pure{"Name"});
12252
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012253 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012254 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012255 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
12257 }
12258 if(not isPublic(\%Type1_Pure, $Member_Pos))
12259 { # do NOT check internal type changes
12260 next;
12261 }
12262 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012263 { # checking member type changes
12264 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12265
12266 my %DupProblems = ();
12267
12268 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012269 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012270 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012272 if(not defined $AllAffected)
12273 {
12274 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12275 next;
12276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012277 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012278
12279 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12280 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12281
12282 if(not defined $AllAffected)
12283 {
12284 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012285 }
12286 }
12287 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012288
12289 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012290 }
12291 }
12292 }
12293 }
12294 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12295 { # checking added members, public and private
12296 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12297 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012298 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012299 if($AddedField{$Member_Pos})
12300 { # added
12301 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12302 {
12303 my $ProblemType = "Added_Field";
12304 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012305 or isUnnamed($Member_Name))
12306 {
12307 if($Level eq "Source") {
12308 next;
12309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012310 $ProblemType = "Added_Private_Field";
12311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012312 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012313 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012314 {
12315 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12316 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012317 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 +040012318 { # changed offset
12319 $ProblemType .= "_And_Layout";
12320 }
12321 }
12322 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12323 $ProblemType .= "_And_Size";
12324 }
12325 }
12326 if($ProblemType eq "Added_Private_Field")
12327 { # skip added private fields
12328 next;
12329 }
12330 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12331 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012332 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012333 }
12334 elsif($Type2_Pure{"Type"} eq "Union")
12335 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012336 if($Level eq "Binary"
12337 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 {
12339 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12340 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012341 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012342 }
12343 else
12344 {
12345 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12346 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012347 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012348 }
12349 }
12350 elsif($Type2_Pure{"Type"} eq "Enum")
12351 {
12352 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12353 next if($Member_Value eq "");
12354 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12355 "Target"=>$Member_Name,
12356 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012357 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012358 }
12359 }
12360 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012362 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012363 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012364}
12365
12366sub isUnnamed($) {
12367 return $_[0]=~/\Aunnamed\d+\Z/;
12368}
12369
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012370sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012371{
12372 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012373 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12374 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12375 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012377 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012378 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012379 }
12380 return $TypeName;
12381}
12382
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012383sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012384{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012385 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012386 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12388 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012389 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012390 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12391 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012392 return () if(not $Type{"Type"});
12393 if($Type{"Type"} ne $Type_Type)
12394 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012395 return () if(not $Type{"BaseType"});
12396 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012397 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012398 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399 return %Type;
12400}
12401
12402my %TypeSpecAttributes = (
12403 "Const" => 1,
12404 "Volatile" => 1,
12405 "ConstVolatile" => 1,
12406 "Restrict" => 1,
12407 "Typedef" => 1
12408);
12409
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012410sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012411{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012412 my ($TypeId, $Info) = @_;
12413 if(not $TypeId or not $Info
12414 or not $Info->{$TypeId}) {
12415 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012416 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012417 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12418 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12419 }
12420 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012421 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012422 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012423 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012424 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012425 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012426 return %Type;
12427}
12428
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012429sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012430{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012431 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012432 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012433 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12434 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012435 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012436 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12437 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012438 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12439 my $PLevel = 0;
12440 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12441 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012442 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012443 return $PLevel if(not $Type{"BaseType"});
12444 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12445 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12446 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012447}
12448
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012449sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012450{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012451 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012453 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12454 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012455 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012456 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12457 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012458 return %Type if(not $Type{"BaseType"});
12459 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012460 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461 return %Type;
12462}
12463
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012464sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012465{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012467 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012468 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12469 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012470 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012471 my $Qual = "";
12472 if($Type{"Type"} eq "Pointer") {
12473 $Qual .= "*";
12474 }
12475 elsif($Type{"Type"} eq "Ref") {
12476 $Qual .= "&";
12477 }
12478 elsif($Type{"Type"} eq "ConstVolatile") {
12479 $Qual .= "const volatile";
12480 }
12481 elsif($Type{"Type"} eq "Const"
12482 or $Type{"Type"} eq "Volatile"
12483 or $Type{"Type"} eq "Restrict") {
12484 $Qual .= lc($Type{"Type"});
12485 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012486 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012487 return $BQual.$Qual;
12488}
12489
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012490sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012491{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012492 my ($TypeId, $Info) = @_;
12493 if(not $TypeId or not $Info
12494 or not $Info->{$TypeId}) {
12495 return ();
12496 }
12497 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012498 return %Type if(not $Type{"BaseType"});
12499 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012500 {
12501 if($Info->{$BTid}) {
12502 return %{$Info->{$BTid}};
12503 }
12504 else { # something is going wrong
12505 return ();
12506 }
12507 }
12508 else {
12509 return %Type;
12510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511}
12512
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012513sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012514{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012515 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012516 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012517 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12518 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519}
12520
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012521sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012522{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012523 my $Symbol = $_[0];
12524 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12525}
12526
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012527sub isInLineInst($$$) {
12528 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12529}
12530
12531sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012532{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012533 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012534 if($CheckObjectsOnly)
12535 {
12536 if($Symbol!~/\A(_Z|\?)/) {
12537 return 0;
12538 }
12539 if(my $Signature = $tr_name{$Symbol})
12540 {
12541 if(index($Signature,">")==-1) {
12542 return 0;
12543 }
12544 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12545 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012546 if(index($ShortName,"<")!=-1
12547 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012548 return 1;
12549 }
12550 }
12551 }
12552 }
12553 else
12554 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012555 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012556 {
12557 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12558 {
12559 if(index($ClassName,"<")!=-1) {
12560 return 1;
12561 }
12562 }
12563 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012564 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012565 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012566 if(index($ShortName,"<")!=-1
12567 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012568 return 1;
12569 }
12570 }
12571 }
12572 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012573}
12574
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012575sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012577 my ($Symbol, $SInfo, $LibVersion) = @_;
12578 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012580 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012581 { # class specialization
12582 return 1;
12583 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012584 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012585 { # method specialization
12586 return 1;
12587 }
12588 }
12589 return 0;
12590}
12591
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012592sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012593{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012594 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012595 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012596 { # non-public global data
12597 return 0;
12598 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012599
12600 if(defined $SkipInternal)
12601 {
12602 return 0 if($Symbol=~/($SkipInternal)/);
12603 }
12604
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 if($CheckObjectsOnly) {
12606 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012608 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 { # support for old ABI dumps in --headers-only mode
12610 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12611 {
12612 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12613 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012614 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 if(not $PType or $PType eq "Unknown") {
12616 return 0;
12617 }
12618 }
12619 }
12620 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012621 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012622 {
12623 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624 if($SkipSymbols{$LibVersion}{$Symbol})
12625 { # user defined symbols to ignore
12626 return 0;
12627 }
12628 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12629 if(not $NameSpace and $ClassId)
12630 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012631 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012632 }
12633 if($NameSpace)
12634 { # user defined namespaces to ignore
12635 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12636 return 0;
12637 }
12638 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12639 { # nested namespaces
12640 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12641 return 0;
12642 }
12643 }
12644 }
12645 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12646 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012647 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 { # --skip-headers or <skip_headers> (not <skip_including>)
12649 if($Skip==1) {
12650 return 0;
12651 }
12652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012653 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012654 if($TypesListPath)
12655 { # user defined types
12656 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12657
12658 if(not $TypesList{$CName})
12659 {
12660 return 0;
12661 }
12662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012663 if($SymbolsListPath and not $SymbolsList{$Symbol})
12664 { # user defined symbols
12665 return 0;
12666 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012667 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12668 { # user defined symbols
12669 return 0;
12670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012671 if($AppPath and not $SymbolsList_App{$Symbol})
12672 { # user defined symbols (in application)
12673 return 0;
12674 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012675 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12676 { # non-target symbols
12677 return 0;
12678 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012679 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012680 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012681 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012682 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012683 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012684 return 0;
12685 }
12686 }
12687 else
12688 {
12689 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012690 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012691 {
12692 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12693 { # inline virtual methods
12694 if($Type=~/InlineVirt/) {
12695 return 1;
12696 }
12697 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12698 if(not $Allocable)
12699 { # check bases
12700 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12701 {
12702 if(not isCopyingClass($DCId, $LibVersion))
12703 { # exists a derived class without default c-tor
12704 $Allocable=1;
12705 last;
12706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012708 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012709 if(not $Allocable) {
12710 return 0;
12711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012712 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012713 else
12714 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 return 0;
12716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012719 }
12720 }
12721 return 1;
12722}
12723
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012724sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012725{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012726 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12728 {
12729 if(link_symbol($Symbol, 1, "+Deps"))
12730 { # linker can find a new symbol
12731 # in the old-version library
12732 # So, it's not a new symbol
12733 next;
12734 }
12735 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012736 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012737 next;
12738 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012739 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012740 }
12741}
12742
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012743sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012744{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012745 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012746 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12747 {
12748 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012749 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012750 }
12751 if(link_symbol($Symbol, 2, "+Deps"))
12752 { # linker can find an old symbol
12753 # in the new-version library
12754 next;
12755 }
12756 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012757 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012758 next;
12759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012760 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012761 }
12762}
12763
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012764sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012765{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012766 my $Level = $_[0];
12767 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 { # checking added symbols
12769 next if($CompleteSignature{2}{$Symbol}{"Private"});
12770 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012771 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012772 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012775 { # checking removed symbols
12776 next if($CompleteSignature{1}{$Symbol}{"Private"});
12777 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012778 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779 { # skip v-tables for templates, that should not be imported by applications
12780 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012781 if(my $CName = $VTableClass{$Symbol})
12782 {
12783 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12784 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012785 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012786 next;
12787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012788 }
12789 }
12790 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012791 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012792 }
12793 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12794 { # symbols for pure virtual methods cannot be called by clients
12795 next;
12796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012797 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 }
12799}
12800
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012801sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012802{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012803 my ($LibVersion, $V) = @_;
12804 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12805 return $Cache{"checkDump"}{$LibVersion}{$V};
12806 }
12807 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012808}
12809
12810sub detectAdded_H($)
12811{
12812 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12814 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012815 if($Level eq "Source")
12816 { # remove symbol version
12817 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12818 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012819
12820 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12821 { # skip artificial constructors
12822 next;
12823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012824 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012825 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12826 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012827 next;
12828 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012829 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012830 next;
12831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012832 if(not defined $CompleteSignature{1}{$Symbol}
12833 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12834 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012835 if($UsedDump{2}{"SrcBin"})
12836 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012837 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012838 { # support for old and different (!) ABI dumps
12839 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12840 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012841 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012842 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012843 {
12844 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12845 {
12846 if($Lang eq "C")
12847 { # support for old ABI dumps: missed extern "C" functions
12848 next;
12849 }
12850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012851 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012852 else
12853 {
12854 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012855 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012856 next;
12857 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012858 }
12859 }
12860 }
12861 }
12862 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012863 }
12864 }
12865}
12866
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012867sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012868{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12871 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012872 if($Level eq "Source")
12873 { # remove symbol version
12874 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12875 $Symbol=$SN;
12876 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012877 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12878 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012879 next;
12880 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012881 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012882 next;
12883 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012884 if(not defined $CompleteSignature{2}{$Symbol}
12885 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012886 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012887 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012888 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012889 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012890 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012891 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12892 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012893 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012894 if($CheckHeadersOnly)
12895 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012896 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12897 {
12898 if($Lang eq "C")
12899 { # support for old ABI dumps: missed extern "C" functions
12900 next;
12901 }
12902 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012904 else
12905 {
12906 if(not link_symbol($Symbol, 1, "-Deps"))
12907 { # skip removed inline symbols
12908 next;
12909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012910 }
12911 }
12912 }
12913 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012914 if(not checkDump(1, "2.15"))
12915 {
12916 if($Symbol=~/_IT_E\Z/)
12917 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12918 next;
12919 }
12920 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012921 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12922 {
12923 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12924 {
12925 if(defined $Constants{2}{$Short})
12926 {
12927 my $Val = $Constants{2}{$Short}{"Value"};
12928 if(defined $Func_ShortName{2}{$Val})
12929 { # old name defined to new
12930 next;
12931 }
12932 }
12933 }
12934
12935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012936 $RemovedInt{$Level}{$Symbol} = 1;
12937 if($Level eq "Source")
12938 { # search for a source-compatible equivalent
12939 setAlternative($Symbol, $Level);
12940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012941 }
12942 }
12943}
12944
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012945sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012946{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012947 my $Level = $_[0];
12948 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012949 { # checking added symbols
12950 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012951 next if($CompleteSignature{2}{$Symbol}{"Private"});
12952 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012953 if($Level eq "Binary")
12954 {
12955 if($CompleteSignature{2}{$Symbol}{"InLine"})
12956 {
12957 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12958 { # skip inline non-virtual functions
12959 next;
12960 }
12961 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012962 }
12963 else
12964 { # Source
12965 if($SourceAlternative_B{$Symbol}) {
12966 next;
12967 }
12968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012971 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012972 { # checking removed symbols
12973 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012974 next if($CompleteSignature{1}{$Symbol}{"Private"});
12975 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012976 if($Level eq "Binary")
12977 {
12978 if($CompleteSignature{1}{$Symbol}{"InLine"})
12979 {
12980 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12981 { # skip inline non-virtual functions
12982 next;
12983 }
12984 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 }
12986 else
12987 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012988 if(my $Alt = $SourceAlternative{$Symbol})
12989 {
12990 if(defined $CompleteSignature{1}{$Alt}
12991 and $CompleteSignature{1}{$Symbol}{"Const"})
12992 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012993 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012994 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012995 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012996 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012997 }
12998 else
12999 { # do NOT show removed symbol
13000 next;
13001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013002 }
13003 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013004 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013005 }
13006}
13007
13008sub addParamNames($)
13009{
13010 my $LibraryVersion = $_[0];
13011 return if(not keys(%AddIntParams));
13012 my $SecondVersion = $LibraryVersion==1?2:1;
13013 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13014 {
13015 next if(not keys(%{$AddIntParams{$Interface}}));
13016 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013017 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013018 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13019 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013020 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013021 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13022 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13023 {
13024 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13025 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13026 }
13027 }
13028 else {
13029 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13030 }
13031 }
13032 }
13033 }
13034}
13035
13036sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013037{ # detect changed typedefs to show
13038 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013039 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13040 {
13041 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013042 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13043 if(not $BName1 or isAnon($BName1)) {
13044 next;
13045 }
13046 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13047 if(not $BName2 or isAnon($BName2)) {
13048 next;
13049 }
13050 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013051 $ChangedTypedef{$Typedef} = 1;
13052 }
13053 }
13054}
13055
13056sub get_symbol_suffix($$)
13057{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013058 my ($Symbol, $Full) = @_;
13059 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013060 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013061 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013062 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013063 if(not $Full) {
13064 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13065 }
13066 return $Suffix;
13067}
13068
13069sub get_symbol_prefix($$)
13070{
13071 my ($Symbol, $LibVersion) = @_;
13072 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13073 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13074 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013075 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013076 }
13077 return $ShortName;
13078}
13079
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013080sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013081{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013082 my $Symbol = $_[0];
13083 my $PSymbol = $Symbol;
13084 if(not defined $CompleteSignature{2}{$PSymbol}
13085 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13086 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13087 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013088 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013089 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013090 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013091 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013092 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13093 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094 {
13095 if(defined $CompleteSignature{2}{$PSymbol}
13096 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13097 {
13098 $SourceAlternative{$Symbol} = $PSymbol;
13099 $SourceAlternative_B{$PSymbol} = $Symbol;
13100 if(not defined $CompleteSignature{1}{$PSymbol}
13101 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13102 $SourceReplacement{$Symbol} = $PSymbol;
13103 }
13104 }
13105 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013106 }
13107 else
13108 {
13109 foreach my $Sp ("KV", "VK", "K", "V")
13110 {
13111 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13112 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13113 {
13114 if(defined $CompleteSignature{2}{$PSymbol}
13115 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13116 {
13117 $SourceAlternative{$Symbol} = $PSymbol;
13118 $SourceAlternative_B{$PSymbol} = $Symbol;
13119 if(not defined $CompleteSignature{1}{$PSymbol}
13120 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13121 $SourceReplacement{$Symbol} = $PSymbol;
13122 }
13123 }
13124 }
13125 $PSymbol = $Symbol;
13126 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013127 }
13128 }
13129 }
13130 return "";
13131}
13132
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013133sub getSymKind($$)
13134{
13135 my ($Symbol, $LibVersion) = @_;
13136 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13137 {
13138 return "Global_Data";
13139 }
13140 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13141 {
13142 return "Method";
13143 }
13144 return "Function";
13145}
13146
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013147sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013148{
13149 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013150 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013151
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013152 mergeBases($Level);
13153
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013154 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013155 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013156 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013157 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013158 next;
13159 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013160 if(defined $CompleteSignature{1}{$Symbol}
13161 and $CompleteSignature{1}{$Symbol}{"Header"})
13162 { # double-check added symbol
13163 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013165 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013166 next;
13167 }
13168 if($Symbol=~/\A(_Z|\?)/)
13169 { # C++
13170 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13171 }
13172 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13173 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013174 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13175 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013176 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013178 {
13179 if($TName_Tid{1}{$AffectedClass_Name})
13180 { # class should exist in previous version
13181 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13182 { # old v-table is NOT copied by old applications
13183 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13184 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013185 "Target"=>get_Signature($Symbol, 2),
13186 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013187 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013190 }
13191 }
13192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013193 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13194 { # check all removed exported symbols
13195 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013196 next;
13197 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013198 if(defined $CompleteSignature{2}{$Symbol}
13199 and $CompleteSignature{2}{$Symbol}{"Header"})
13200 { # double-check removed symbol
13201 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013202 }
13203 if($CompleteSignature{1}{$Symbol}{"Private"})
13204 { # skip private methods
13205 next;
13206 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013207 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013208 next;
13209 }
13210 $CheckedSymbols{$Level}{$Symbol} = 1;
13211 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13212 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013213 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13214 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013215 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013216 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13217 {
13218 if($TName_Tid{2}{$AffectedClass_Name})
13219 { # class should exist in newer version
13220 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13221 { # old v-table is NOT copied by old applications
13222 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13223 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013224 "Target"=>get_Signature($OverriddenMethod, 1),
13225 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013226 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013229 }
13230 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013231 if($Level eq "Binary"
13232 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013233 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013234 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013235 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013236 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013237 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013238 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013239 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013240 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013241 {
13242 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13243 "Target"=>$tr_name{$Symbol},
13244 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013245 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013246 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013247 else
13248 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013249 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013250 "Target"=>$tr_name{$Symbol},
13251 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013252 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013253 }
13254 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013255 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013257 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013258 {
13259 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13260 "Target"=>$tr_name{$Symbol},
13261 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013262 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013263 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 else
13265 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013266 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013267 "Target"=>$tr_name{$Symbol},
13268 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 }
13271 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013272 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13273 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13274 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13275 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13276 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 {
13278 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013279 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013280 $ProblemType = "Global_Data_Symbol_Changed_Type";
13281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013282 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13283 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013284 "Old_Type"=>$RTName1,
13285 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013286 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013287 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013288 }
13289 }
13290 }
13291 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013292 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013293 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013295 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013296 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013297 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013298 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013299 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13300 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013301 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013302 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013304 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013305 }
13306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013307 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13308 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013309 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013310 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013312 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013313 }
13314 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013315 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013316 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013317 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013318 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013320 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013321 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013322 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013323 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013324 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013325 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013326 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013327 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013328 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013330 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013331 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013332 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013333 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013334 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013335 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013336 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013338 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013339 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 { # "volatile" to non-"volatile"
13341
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013342 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013343 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013344 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013351 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013354 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013355 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013356 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13360 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013361 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 }
13365 }
13366 }
13367 }
13368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13370 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013371 $CurrentSymbol = $Symbol;
13372
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013373 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13374 if($Level eq "Source")
13375 { # remove symbol version
13376 $Symbol=$SN;
13377 }
13378 else
13379 { # Binary
13380 if(not $SV)
13381 { # symbol without version
13382 if(my $VSym = $SymVer{1}{$Symbol})
13383 { # the symbol is linked with versioned symbol
13384 if($CompleteSignature{2}{$VSym}{"MnglName"})
13385 { # show report for symbol@ver only
13386 next;
13387 }
13388 elsif(not link_symbol($VSym, 2, "-Deps"))
13389 { # changed version: sym@v1 to sym@v2
13390 # do NOT show report for symbol
13391 next;
13392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 }
13394 }
13395 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013396 my $PSymbol = $Symbol;
13397 if($Level eq "Source"
13398 and my $S = $SourceReplacement{$Symbol})
13399 { # take a source-compatible replacement function
13400 $PSymbol = $S;
13401 }
13402 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013403 { # private symbols
13404 next;
13405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 if(not defined $CompleteSignature{1}{$Symbol}
13407 or not defined $CompleteSignature{2}{$PSymbol})
13408 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 next;
13410 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013411 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13412 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13413 { # no mangled name
13414 next;
13415 }
13416 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13417 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 { # without a header
13419 next;
13420 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013421
13422 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13423 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13424 { # became pure
13425 next;
13426 }
13427 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13428 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13429 { # became non-pure
13430 next;
13431 }
13432
13433 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13434 { # exported, target, inline virtual and pure virtual
13435 next;
13436 }
13437 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13438 { # exported, target, inline virtual and pure virtual
13439 next;
13440 }
13441
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013442 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013443 {
13444 if($CompleteSignature{1}{$Symbol}{"Data"}
13445 and $CompleteSignature{2}{$PSymbol}{"Data"})
13446 {
13447 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13448 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13449 if(defined $Value1)
13450 {
13451 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13452 if(defined $Value2)
13453 {
13454 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13455 if($Value1 ne $Value2)
13456 {
13457 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13458 "Old_Value"=>$Value1,
13459 "New_Value"=>$Value2,
13460 "Target"=>get_Signature($Symbol, 1) );
13461 }
13462 }
13463 }
13464 }
13465 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013466
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013467 if($CompleteSignature{2}{$PSymbol}{"Private"})
13468 {
13469 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13470 "Target"=>get_Signature_M($PSymbol, 2) );
13471 }
13472 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13473 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13474 {
13475 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13476 "Target"=>get_Signature_M($PSymbol, 2) );
13477 }
13478 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13479 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13480 {
13481 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13482 "Target"=>get_Signature_M($PSymbol, 2) );
13483 }
13484
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013486 mergeVirtualTables($Symbol, $Level);
13487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013488 if($COMPILE_ERRORS)
13489 { # if some errors occurred at the compiling stage
13490 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013491 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013492 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013493 { # missed information about parameters in newer version
13494 next;
13495 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013496 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013497 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013498 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 next;
13500 }
13501 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013502 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013503 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013504 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013505 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13506 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013507 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13508 "Target"=>get_Signature($Symbol, 1)
13509 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013510 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013511 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013512 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13513 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013514 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013515 "Target"=>get_Signature($Symbol, 1)
13516 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013518 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13519 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013521 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013523 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13524 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13525 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013526 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013527 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013528 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13529 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013531 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013532 my $ProblemType = "Virtual_Method_Position";
13533 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13534 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013535 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013536 if(isUsedClass($Class_Id, 1, $Level))
13537 {
13538 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013539 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013540 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013541 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13542 next;
13543 }
13544 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013545 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013546 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13547 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013548 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013549 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013550 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013552 }
13553 }
13554 }
13555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013556 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13557 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013558 { # do NOT check type changes in pure virtuals
13559 next;
13560 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013561 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013562 if($Symbol=~/\A(_Z|\?)/
13563 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013565 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013566 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013567 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013568 }
13569 }
13570 else
13571 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013572 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013573 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013574 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013575 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13576 last if($PType2_Name eq "...");
13577 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13578 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013580 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013581 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013582 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13583 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013584 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13585 $ParamPos_Prev = "lost";
13586 }
13587 }
13588 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013589 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013590 }
13591 if($ParamPos_Prev eq "lost")
13592 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013593 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013594 {
13595 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013596 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 $ProblemType = "Added_Unnamed_Parameter";
13598 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013599 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013600 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013601 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013602 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013603 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013604 }
13605 else
13606 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013607 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013608 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013609 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013610 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13611 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013612 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013613 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013614 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013615 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013616 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013617 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013618 "Param_Type"=>$PType2_Name,
13619 "Old_Value"=>$PName_Old,
13620 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013621 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 }
13623 }
13624 else
13625 {
13626 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013627 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 $ProblemType = "Added_Middle_Unnamed_Parameter";
13629 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013630 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013631 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013632 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013633 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013634 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 }
13636 }
13637 }
13638 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013639 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013641 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013642 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013643 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013644 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013645 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013646 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013647 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013648 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13649 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013650 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013651 }
13652 }
13653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013656 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013657 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13658 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013659 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13660 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013661 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013662 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013663 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013664 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13665 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13667 $ParamPos_New = "lost";
13668 }
13669 }
13670 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013671 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013672 }
13673 if($ParamPos_New eq "lost")
13674 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013675 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 {
13677 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013678 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013679 $ProblemType = "Removed_Unnamed_Parameter";
13680 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013681 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013682 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013683 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013684 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013685 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013687 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013689 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013690 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013691 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013692 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013693 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013694 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013695 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013696 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013697 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013698 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013699 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013700 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013701 "Old_Value"=>$PName,
13702 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013703 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013704 }
13705 }
13706 else
13707 {
13708 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013709 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013710 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13711 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013712 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013713 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013714 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013715 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013716 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013717 }
13718 }
13719 }
13720 }
13721 }
13722 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013723 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13724 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013725 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013726
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013727 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013728 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013729 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13730 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013731 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013732
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013733 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013734 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013735 if($SubProblemType eq "Return_Type_And_Size") {
13736 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13737 }
13738 elsif($SubProblemType eq "Return_Type_Format") {
13739 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13740 }
13741 else {
13742 $ProblemTypes{"Global_Data_Type"} = 1;
13743 }
13744
13745 # quals
13746 if($SubProblemType eq "Return_Type"
13747 or $SubProblemType eq "Return_Type_And_Size"
13748 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013749 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013750 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13751 { # const to non-const
13752 if($RR==2) {
13753 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13754 }
13755 else {
13756 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13757 }
13758 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013759 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013760 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13761 { # non-const to const
13762 if($RA==2) {
13763 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13764 }
13765 else {
13766 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13767 }
13768 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013769 }
13770 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013771 }
13772 else
13773 {
13774 # quals
13775 if($SubProblemType eq "Return_Type"
13776 or $SubProblemType eq "Return_Type_And_Size"
13777 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013778 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013779 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013780 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013781 if(addedQual($Old_Value, $New_Value, "volatile"))
13782 {
13783 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13784 if($Level ne "Source"
13785 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13786 $ProblemTypes{"Return_Type"} = 1;
13787 }
13788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013789 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013790 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13791 {
13792 if($RA==2) {
13793 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13794 }
13795 else {
13796 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13797 }
13798 if($Level ne "Source"
13799 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13800 $ProblemTypes{"Return_Type"} = 1;
13801 }
13802 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013803 }
13804 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013805 if($Level eq "Binary"
13806 and not $CompleteSignature{1}{$Symbol}{"Data"})
13807 {
13808 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13809 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13810 { # if one of the architectures is unknown
13811 # then set other arhitecture to unknown too
13812 ($Arch1, $Arch2) = ("unknown", "unknown");
13813 }
13814 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013815 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013816 {
13817 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13818 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13819 }
13820 else
13821 {
13822 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13823 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13824 }
13825
13826 if($SubProblemType eq "Return_Type_Became_Void")
13827 {
13828 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13829 { # parameters stack has been affected
13830 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013831 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013832 }
13833 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013834 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013835 }
13836 }
13837 }
13838 elsif($SubProblemType eq "Return_Type_From_Void")
13839 {
13840 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13841 { # parameters stack has been affected
13842 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013843 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013844 }
13845 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013847 }
13848 }
13849 }
13850 elsif($SubProblemType eq "Return_Type"
13851 or $SubProblemType eq "Return_Type_And_Size"
13852 or $SubProblemType eq "Return_Type_Format")
13853 {
13854 if($Conv1{"Method"} ne $Conv2{"Method"})
13855 {
13856 if($Conv1{"Method"} eq "stack")
13857 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013859 }
13860 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013861 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013862 }
13863 }
13864 else
13865 {
13866 if($Conv1{"Method"} eq "reg")
13867 {
13868 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13869 {
13870 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013871 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013872 }
13873 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013874 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013875 }
13876 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013877 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013878 }
13879 }
13880 }
13881 }
13882 }
13883 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013884
13885 if(not keys(%ProblemTypes))
13886 { # default
13887 $ProblemTypes{$SubProblemType} = 1;
13888 }
13889
13890 foreach my $ProblemType (keys(%ProblemTypes))
13891 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013892 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013894 }
13895 if($ReturnType1_Id and $ReturnType2_Id)
13896 {
13897 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013898 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13899
13900 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013901
13902 if($CompleteSignature{1}{$Symbol}{"Data"})
13903 {
13904 if($Level eq "Binary")
13905 {
13906 if(get_PLevel($ReturnType1_Id, 1)==0)
13907 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013908 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013909 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013910
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013911 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13912 {
13913 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013914 {
13915 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13916 {
13917 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13918 last;
13919 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013920 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013921 }
13922 }
13923 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013924 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013925 {
13926 if(defined $GlobalDataObject{1}{$Symbol}
13927 and defined $GlobalDataObject{2}{$Symbol})
13928 {
13929 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13930 my $New_Size = $GlobalDataObject{2}{$Symbol};
13931 if($Old_Size!=$New_Size)
13932 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013933 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013934 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013935 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013936 }
13937 }
13938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013939 }
13940 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013941
13942 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013943 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013944 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013945 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013946 my $NewLocation = "retval";
13947 if($SubLocation and $SubLocation ne "retval") {
13948 $NewLocation = "retval->".$SubLocation;
13949 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013950 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13951 }
13952 }
13953
13954 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13955 {
13956 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13957 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013958 my $NewLocation = "retval";
13959 if($SubLocation and $SubLocation ne "retval") {
13960 $NewLocation = "retval->".$SubLocation;
13961 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013962 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013963 }
13964 }
13965 }
13966
13967 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013968 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13969 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13970 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013971 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013972 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013973 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13974 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013975 if($ThisPtr1_Id and $ThisPtr2_Id)
13976 {
13977 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013978 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13979 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013980 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013981 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013982 {
13983 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013984 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013985 }
13986 }
13987 }
13988 }
13989 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013990 if($Level eq "Binary") {
13991 mergeVTables($Level);
13992 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013993 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13994 $CheckedSymbols{$Level}{$Symbol} = 1;
13995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013996}
13997
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013998sub rmQuals($$)
13999{
14000 my ($Value, $Qual) = @_;
14001 if(not $Qual) {
14002 return $Value;
14003 }
14004 if($Qual eq "all")
14005 { # all quals
14006 $Qual = "const|volatile|restrict";
14007 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014008 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014009 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014010 }
14011 return $Value;
14012}
14013
14014sub cmpBTypes($$$$)
14015{
14016 my ($T1, $T2, $V1, $V2) = @_;
14017 $T1 = uncover_typedefs($T1, $V1);
14018 $T2 = uncover_typedefs($T2, $V2);
14019 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14020}
14021
14022sub addedQual($$$)
14023{
14024 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014025 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014026}
14027
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014028sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014029{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014030 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014031 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014032}
14033
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014034sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014035{
14036 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14037 $Old_Value = uncover_typedefs($Old_Value, $V1);
14038 $New_Value = uncover_typedefs($New_Value, $V2);
14039 if($Old_Value eq $New_Value)
14040 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014041 return 0;
14042 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014043 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014044 { # without a qual
14045 return 0;
14046 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014047 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014048 { # became non-qual
14049 return 1;
14050 }
14051 else
14052 {
14053 my @BQ1 = getQualModel($Old_Value, $Qual);
14054 my @BQ2 = getQualModel($New_Value, $Qual);
14055 foreach (0 .. $#BQ1)
14056 { # removed qual
14057 if($BQ1[$_]==1
14058 and $BQ2[$_]!=1)
14059 {
14060 return 2;
14061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014062 }
14063 }
14064 return 0;
14065}
14066
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014067sub getQualModel($$)
14068{
14069 my ($Value, $Qual) = @_;
14070 if(not $Qual) {
14071 return $Value;
14072 }
14073
14074 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014075 while($Value=~/(\w+)/ and $1 ne $Qual) {
14076 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014077 }
14078 $Value=~s/[^\*\&\w]+//g;
14079
14080 # modeling
14081 # int*const*const == 011
14082 # int**const == 001
14083 my @Model = ();
14084 my @Elems = split(/[\*\&]/, $Value);
14085 if(not @Elems) {
14086 return (0);
14087 }
14088 foreach (@Elems)
14089 {
14090 if($_ eq $Qual) {
14091 push(@Model, 1);
14092 }
14093 else {
14094 push(@Model, 0);
14095 }
14096 }
14097
14098 return @Model;
14099}
14100
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014101my %StringTypes = map {$_=>1} (
14102 "char*",
14103 "char const*"
14104);
14105
14106my %CharTypes = map {$_=>1} (
14107 "char",
14108 "char const"
14109);
14110
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014111sub showVal($$$)
14112{
14113 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014114 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014115 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014116 if(substr($Value, 0, 2) eq "_Z")
14117 {
14118 if(my $Unmangled = $tr_name{$Value}) {
14119 return $Unmangled;
14120 }
14121 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014122 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014123 { # strings
14124 return "\"$Value\"";
14125 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014126 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014127 { # characters
14128 return "\'$Value\'";
14129 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014130 if($Value eq "")
14131 { # other
14132 return "\'\'";
14133 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014134 return $Value;
14135}
14136
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014137sub getRegs($$$)
14138{
14139 my ($LibVersion, $Symbol, $Pos) = @_;
14140
14141 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14142 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014143 my %Regs = ();
14144 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14145 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014146 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014147 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14148 }
14149 }
14150
14151 return join(", ", sort keys(%Regs));
14152 }
14153
14154 return undef;
14155}
14156
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014157sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014158{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014159 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014160 if(not $Symbol) {
14161 return;
14162 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014163 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14164 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14165 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14166 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014167 if(not $PType1_Id
14168 or not $PType2_Id) {
14169 return;
14170 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014171
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014172 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014173 { # do not merge "this"
14174 if($PName1 eq "this" or $PName2 eq "this") {
14175 return;
14176 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014177 }
14178
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014179 my %Type1 = get_Type($PType1_Id, 1);
14180 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014181
14182 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14183
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014184 my %BaseType1 = get_BaseType($PType1_Id, 1);
14185 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014186
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014187 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014188
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014189 if($Level eq "Binary")
14190 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014191 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014192 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14193 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14194 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14195 {
14196 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014197 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014198 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014199 }
14200 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14201 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14202 {
14203 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014204 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014205 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014207 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014208
14209 if(defined $UsedDump{1}{"DWARF"}
14210 and defined $UsedDump{2}{"DWARF"})
14211 {
14212 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14213 {
14214 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14215 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14216 if($Old_Regs and $New_Regs)
14217 {
14218 if($Old_Regs ne $New_Regs)
14219 {
14220 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14221 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014222 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014223 "Old_Value"=>$Old_Regs,
14224 "New_Value"=>$New_Regs );
14225 }
14226 }
14227 elsif($Old_Regs and not $New_Regs)
14228 {
14229 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14230 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014231 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014232 "Old_Value"=>$Old_Regs );
14233 }
14234 elsif(not $Old_Regs and $New_Regs)
14235 {
14236 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14237 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014238 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014239 "New_Value"=>$New_Regs );
14240 }
14241 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14242 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14243 {
14244 if($Old_Offset ne $New_Offset)
14245 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014246 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14247 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14248
14249 $Old_Offset = $Old_Offset - $Start1;
14250 $New_Offset = $New_Offset - $Start2;
14251
14252 if($Old_Offset ne $New_Offset)
14253 {
14254 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14255 "Target"=>$PName1,
14256 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14257 "Old_Value"=>$Old_Offset,
14258 "New_Value"=>$New_Offset );
14259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014260 }
14261 }
14262 }
14263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014264 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014265 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14266 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014268 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014269 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14270 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014271 if(not checkDump(1, "2.13")
14272 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014273 { # support for old ABI dumps
14274 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014275 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014276 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014277 and $Value_Old eq "false" and $Value_New eq "0")
14278 { # int class::method ( bool p = 0 );
14279 # old ABI dumps: "false"
14280 # new ABI dumps: "0"
14281 $Value_Old = "0";
14282 }
14283 }
14284 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014285 if(not checkDump(1, "2.18")
14286 and checkDump(2, "2.18"))
14287 { # support for old ABI dumps
14288 if(not defined $Value_Old
14289 and substr($Value_New, 0, 2) eq "_Z") {
14290 $Value_Old = $Value_New;
14291 }
14292 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014293 if(defined $Value_Old)
14294 {
14295 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14296 if(defined $Value_New)
14297 {
14298 $Value_New = showVal($Value_New, $PType2_Id, 2);
14299 if($Value_Old ne $Value_New)
14300 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014301 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014302 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014303 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014304 "Old_Value"=>$Value_Old,
14305 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014306 }
14307 }
14308 else
14309 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014310 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014311 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014312 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014313 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 }
14315 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014316 elsif(defined $Value_New)
14317 {
14318 $Value_New = showVal($Value_New, $PType2_Id, 2);
14319 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14320 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014321 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014322 "New_Value"=>$Value_New );
14323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014324 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014325
14326 if($ChkRnmd)
14327 {
14328 if($PName1 and $PName2 and $PName1 ne $PName2
14329 and $PType1_Id!=-1 and $PType2_Id!=-1
14330 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14331 { # except unnamed "..." value list (Id=-1)
14332 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14333 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014334 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014335 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14336 "Old_Value"=>$PName1,
14337 "New_Value"=>$PName2,
14338 "New_Signature"=>get_Signature($Symbol, 2) );
14339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014340 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014342 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014343 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014344
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014345 foreach my $SubProblemType (keys(%SubProblems))
14346 { # add new problems, remove false alarms
14347 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14348 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014349
14350 # quals
14351 if($SubProblemType eq "Parameter_Type"
14352 or $SubProblemType eq "Parameter_Type_And_Size"
14353 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014354 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014355 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014356 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014357 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014358 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014359 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014360 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14361 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14362 }
14363 }
14364 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14365 {
14366 if(removedQual($Old_Value, $New_Value, "volatile")) {
14367 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014368 }
14369 }
14370 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14371 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14372 { # int to "int const"
14373 delete($SubProblems{$SubProblemType});
14374 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014375 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014376 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14377 { # "int const" to int
14378 delete($SubProblems{$SubProblemType});
14379 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014380 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14381 { # "const" to non-"const"
14382 if($RR==2) {
14383 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14384 }
14385 else {
14386 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14387 }
14388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014389 }
14390 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014391
14392 if($Level eq "Source")
14393 {
14394 foreach my $SubProblemType (keys(%SubProblems))
14395 {
14396 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14397 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14398
14399 if($SubProblemType eq "Parameter_Type")
14400 {
14401 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14402 delete($SubProblems{$SubProblemType});
14403 }
14404 }
14405 }
14406 }
14407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014408 foreach my $SubProblemType (keys(%SubProblems))
14409 { # modify/register problems
14410 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14411 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014412 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14413 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014414
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014415 my $NewProblemType = $SubProblemType;
14416 if($Old_Value eq "..." and $New_Value ne "...")
14417 { # change from "..." to "int"
14418 if($ParamPos1==0)
14419 { # ISO C requires a named argument before "..."
14420 next;
14421 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014422 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014423 }
14424 elsif($New_Value eq "..." and $Old_Value ne "...")
14425 { # change from "int" to "..."
14426 if($ParamPos2==0)
14427 { # ISO C requires a named argument before "..."
14428 next;
14429 }
14430 $NewProblemType = "Parameter_Became_VaList";
14431 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014432 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014433 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014434 {
14435 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014436 if($Arch1 eq "unknown"
14437 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014438 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014439 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014440 ($Arch1, $Arch2) = ("unknown", "unknown");
14441 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014442 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014443 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014444 { # real
14445 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14446 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14447 }
14448 else
14449 { # model
14450 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14451 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14452 }
14453 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014454 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014455 if($Conv1{"Method"} eq "stack")
14456 {
14457 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14458 $NewProblemType = "Parameter_Type_And_Stack";
14459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014460 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014461 elsif($Conv1{"Method"} eq "reg")
14462 {
14463 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14464 $NewProblemType = "Parameter_Type_And_Register";
14465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014466 }
14467 }
14468 else
14469 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014470 if($Conv1{"Method"} eq "stack") {
14471 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014472 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014473 elsif($Conv1{"Method"} eq "register") {
14474 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 }
14476 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014477 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14478 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014479 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014480 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014481 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014482 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014483 "New_Signature"=>get_Signature($Symbol, 2) );
14484 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014485 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014486
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014487 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014488
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014490 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14491 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014492 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014493 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014494 {
14495 my $NewProblemType = $SubProblemType;
14496 if($SubProblemType eq "DataType_Size")
14497 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014498 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014499 { # stack has been affected
14500 $NewProblemType = "DataType_Size_And_Stack";
14501 }
14502 }
14503 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014504 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014505 }
14506 }
14507}
14508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014509sub find_ParamPair_Pos_byName($$$)
14510{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014511 my ($Name, $Symbol, $LibVersion) = @_;
14512 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014513 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014514 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14515 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014516 {
14517 return $ParamPos;
14518 }
14519 }
14520 return "lost";
14521}
14522
14523sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14524{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014525 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014527 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014528 {
14529 next if($Order eq "backward" and $ParamPos>$MediumPos);
14530 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014531 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14532 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014533 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014534 push(@Positions, $ParamPos);
14535 }
14536 }
14537 return @Positions;
14538}
14539
14540sub getTypeIdByName($$)
14541{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014542 my ($TypeName, $LibVersion) = @_;
14543 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014544}
14545
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014546sub diffTypes($$$)
14547{
14548 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14549 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14550 }
14551 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14552 { # skip recursive declarations
14553 return 0;
14554 }
14555
14556 pushType($_[0], $_[1], \@RecurTypes_Diff);
14557 my $Diff = diffTypes_I(@_);
14558 pop(@RecurTypes_Diff);
14559
14560 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14561}
14562
14563sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014564{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014565 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014566
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014567 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14568 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014569
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014570 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14571 { # equal types
14572 return 0;
14573 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014574 if($Type1_Pure{"Name"} eq "void")
14575 { # from void* to something
14576 return 0;
14577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014578 if($Type1_Pure{"Name"}=~/\*/
14579 or $Type2_Pure{"Name"}=~/\*/)
14580 { # compared in detectTypeChange()
14581 return 0;
14582 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014583
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014584 my %FloatType = map {$_=>1} (
14585 "float",
14586 "double",
14587 "long double"
14588 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014589
14590 my $T1 = $Type1_Pure{"Type"};
14591 my $T2 = $Type2_Pure{"Type"};
14592
14593 if($T1 eq "Struct"
14594 and $T2 eq "Class")
14595 { # compare as data structures
14596 $T2 = "Struct";
14597 }
14598
14599 if($T1 eq "Class"
14600 and $T2 eq "Struct")
14601 { # compare as data structures
14602 $T1 = "Struct";
14603 }
14604
14605 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014607 if($T1 eq "Intrinsic"
14608 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014609 { # "int" to "enum"
14610 return 0;
14611 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014612 elsif($T2 eq "Intrinsic"
14613 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014614 { # "enum" to "int"
14615 return 0;
14616 }
14617 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014618 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014619 # ...
14620 return 1;
14621 }
14622 }
14623 else
14624 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014625 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014626 {
14627 if($FloatType{$Type1_Pure{"Name"}}
14628 or $FloatType{$Type2_Pure{"Name"}})
14629 { # "float" to "double"
14630 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014631 if($Level eq "Source")
14632 { # Safe
14633 return 0;
14634 }
14635 else {
14636 return 1;
14637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014638 }
14639 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014640 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014641 {
14642 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14643 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014644 if(not @Membs1
14645 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014646 { # private
14647 return 0;
14648 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 if($#Membs1!=$#Membs2)
14650 { # different number of elements
14651 return 1;
14652 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014653 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014654 {
14655 foreach my $Pos (@Membs1)
14656 { # compare elements by name and value
14657 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14658 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14659 { # different names
14660 return 1;
14661 }
14662 }
14663 }
14664 else
14665 {
14666 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014667 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014668 if($Level eq "Source")
14669 {
14670 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14671 { # different names
14672 return 1;
14673 }
14674 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014675
14676 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14677 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14678
14679 if($MT1{"Name"} ne $MT2{"Name"}
14680 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14681 {
14682 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14683 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14684
14685 if($PL1 ne $PL2)
14686 { # different pointer level
14687 return 1;
14688 }
14689
14690 # compare base types
14691 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14692 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14693
14694 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14695 { # different types
14696 return 1;
14697 }
14698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014699 }
14700 }
14701 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014702 else
14703 {
14704 # TODO: arrays, etc.
14705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014706 }
14707 return 0;
14708}
14709
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014710sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014711{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014712 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014713 if(not $Type1_Id or not $Type2_Id) {
14714 return ();
14715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014716 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014717 my %Type1 = get_Type($Type1_Id, 1);
14718 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014719 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14720 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14721 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14722 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 +040014723
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014724 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14725 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014726 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14727 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14728 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14729 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14730 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14731 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14732 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014733 if($Type1{"Name"} eq $Type2{"Name"})
14734 {
14735 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14736 { # will be reported in mergeTypes() as typedef problem
14737 return ();
14738 }
14739 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14740 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14741 if(%Typedef_1 and %Typedef_2)
14742 {
14743 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14744 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14745 { # const Typedef
14746 return ();
14747 }
14748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014749 }
14750 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14751 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014752 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014753 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14754 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014755 {
14756 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14757 "Old_Value"=>$Type1_Base{"Name"},
14758 "New_Value"=>$Type2_Base{"Name"},
14759 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014760 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014761 }
14762 else
14763 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014764 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014765 { # format change
14766 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14767 "Old_Value"=>$Type1_Base{"Name"},
14768 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014769 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014770 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014771 }
14772 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14773 {
14774 %{$LocalProblems{$Prefix."_BaseType"}}=(
14775 "Old_Value"=>$Type1_Base{"Name"},
14776 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014777 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014778 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014779 }
14780 }
14781 }
14782 }
14783 elsif($Type1{"Name"} ne $Type2{"Name"})
14784 { # type change
14785 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14786 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014787 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014788 and $Type1_Pure{"Name"} eq "void")
14789 {
14790 %{$LocalProblems{"Return_Type_From_Void"}}=(
14791 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014792 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014794 elsif($Prefix eq "Return"
14795 and $Type2_Pure{"Name"} eq "void")
14796 {
14797 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14798 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014799 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014801 else
14802 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014803 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014804 and $Type1{"Size"} and $Type2{"Size"}
14805 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014806 {
14807 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14808 "Old_Value"=>$Type1{"Name"},
14809 "New_Value"=>$Type2{"Name"},
14810 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014811 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014812 }
14813 else
14814 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014815 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014816 { # format change
14817 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14818 "Old_Value"=>$Type1{"Name"},
14819 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014820 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014821 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822 }
14823 elsif(tNameLock($Type1_Id, $Type2_Id))
14824 { # FIXME: correct this condition
14825 %{$LocalProblems{$Prefix."_Type"}}=(
14826 "Old_Value"=>$Type1{"Name"},
14827 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014828 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014829 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014830 }
14831 }
14832 }
14833 }
14834 }
14835 if($Type1_PLevel!=$Type2_PLevel)
14836 {
14837 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14838 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14839 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014840 if($Level eq "Source")
14841 {
14842 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014843 "Old_Value"=>$Type1_PLevel,
14844 "New_Value"=>$Type2_PLevel);
14845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014846 else
14847 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014848 if($Type2_PLevel>$Type1_PLevel)
14849 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014850 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14851 "Old_Value"=>$Type1_PLevel,
14852 "New_Value"=>$Type2_PLevel);
14853 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014854 else
14855 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014856 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14857 "Old_Value"=>$Type1_PLevel,
14858 "New_Value"=>$Type2_PLevel);
14859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 }
14861 }
14862 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014863 if($Type1_Pure{"Type"} eq "Array"
14864 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865 { # base_type[N] -> base_type[N]
14866 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014867 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014868 foreach my $SubProblemType (keys(%SubProblems))
14869 {
14870 $SubProblemType=~s/_Type/_BaseType/g;
14871 next if(defined $LocalProblems{$SubProblemType});
14872 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14873 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14874 }
14875 }
14876 }
14877 return %LocalProblems;
14878}
14879
14880sub tNameLock($$)
14881{
14882 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014883 my $Changed = 0;
14884 if(differentDumps("G"))
14885 { # different GCC versions
14886 $Changed = 1;
14887 }
14888 elsif(differentDumps("V"))
14889 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014890 if(not checkDump(1, "2.20")
14891 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014892 { # latest names update
14893 # 2.6: added restrict qualifier
14894 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014895 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014896 $Changed = 1;
14897 }
14898 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014899
14900 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14901 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14902
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014903 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14904 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14905
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014906 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014907 { # different formats
14908 if($UseOldDumps)
14909 { # old dumps
14910 return 0;
14911 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014912
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014913 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014914 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014915 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014916 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014917 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014918 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014919 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014921 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14922 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14923 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014924 { # equal base types
14925 return 0;
14926 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014927
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014928 if(not checkDump(1, "2.13")
14929 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014930 { # broken array names in ABI dumps < 2.13
14931 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014932 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014933 return 0;
14934 }
14935 }
14936
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014937 if(not checkDump(1, "2.6")
14938 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014939 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014940 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014941 and $TN2=~/\brestrict\b/) {
14942 return 0;
14943 }
14944 }
14945
14946 if(not checkDump(1, "2.20")
14947 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014948 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014949 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14950 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014951 return 0;
14952 }
14953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014955 else
14956 {
14957 # typedef struct {...} type_t
14958 # typedef struct type_t {...} type_t
14959 if(index($TN1, " ".$TN2)!=-1)
14960 {
14961 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14962 return 0;
14963 }
14964 }
14965 if(index($TN2, " ".$TN1)!=-1)
14966 {
14967 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14968 return 0;
14969 }
14970 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014971
14972 if($TT1 eq "FuncPtr"
14973 and $TT2 eq "FuncPtr")
14974 {
14975 my $TN1_C = $TN1;
14976 my $TN2_C = $TN2;
14977
14978 $TN1_C=~s/\b(struct|union) //g;
14979 $TN2_C=~s/\b(struct|union) //g;
14980
14981 if($TN1_C eq $TN2_C) {
14982 return 0;
14983 }
14984 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014985 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014986
14987 my ($N1, $N2) = ($TN1, $TN2);
14988 $N1=~s/\b(struct|union) //g;
14989 $N2=~s/\b(struct|union) //g;
14990
14991 if($N1 eq $N2)
14992 { # QList<struct QUrl> and QList<QUrl>
14993 return 0;
14994 }
14995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014996 return 1;
14997}
14998
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014999sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015001 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015002 if(defined $Cache{"differentDumps"}{$Check}) {
15003 return $Cache{"differentDumps"}{$Check};
15004 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015005 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015006 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015007 if($Check eq "G")
15008 {
15009 if(getGccVersion(1) ne getGccVersion(2))
15010 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015011 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015012 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015013 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015014 if($Check eq "V")
15015 {
15016 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15017 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15018 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015019 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015020 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015023 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015024}
15025
15026sub formatVersion($$)
15027{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015028 my ($V, $Digits) = @_;
15029 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015030 return join(".", splice(@Elems, 0, $Digits));
15031}
15032
15033sub htmlSpecChars($)
15034{
15035 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015036 if(not $Str) {
15037 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15040 $Str=~s/</&lt;/g;
15041 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15042 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015043 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15044 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015045 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015046 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015047 $Str=~s/\n/<br\/>/g;
15048 $Str=~s/\"/&quot;/g;
15049 $Str=~s/\'/&#39;/g;
15050 return $Str;
15051}
15052
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015053sub xmlSpecChars($)
15054{
15055 my $Str = $_[0];
15056 if(not $Str) {
15057 return $Str;
15058 }
15059
15060 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15061 $Str=~s/</&lt;/g;
15062 $Str=~s/>/&gt;/g;
15063
15064 $Str=~s/\"/&quot;/g;
15065 $Str=~s/\'/&#39;/g;
15066
15067 return $Str;
15068}
15069
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015070sub xmlSpecChars_R($)
15071{
15072 my $Str = $_[0];
15073 if(not $Str) {
15074 return $Str;
15075 }
15076
15077 $Str=~s/&amp;/&/g;
15078 $Str=~s/&lt;/</g;
15079 $Str=~s/&gt;/>/g;
15080
15081 $Str=~s/&quot;/"/g;
15082 $Str=~s/&#39;/'/g;
15083
15084 return $Str;
15085}
15086
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015087sub black_name($)
15088{
15089 my $Name = $_[0];
15090 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15091}
15092
15093sub highLight_Signature($)
15094{
15095 my $Signature = $_[0];
15096 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15097}
15098
15099sub highLight_Signature_Italic_Color($)
15100{
15101 my $Signature = $_[0];
15102 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15103}
15104
15105sub separate_symbol($)
15106{
15107 my $Symbol = $_[0];
15108 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15109 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15110 ($Name, $Spec, $Ver) = ($1, $2, $3);
15111 }
15112 return ($Name, $Spec, $Ver);
15113}
15114
15115sub cut_f_attrs($)
15116{
15117 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15118 return $2;
15119 }
15120 return "";
15121}
15122
15123sub highLight_Signature_PPos_Italic($$$$$)
15124{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015125 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15126 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015127 if($CheckObjectsOnly) {
15128 $ItalicParams=$ColorParams=0;
15129 }
15130 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15131 my $Return = "";
15132 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15133 $Return = $2;
15134 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015135 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015136 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015137 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015138 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015139 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015140 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015141 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015142 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015143 }
15144 return $Signature;
15145 }
15146 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15147 $Begin.=" " if($Begin!~/ \Z/);
15148 $End = cut_f_attrs($Signature);
15149 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015150 my ($Short, $Params) = split_Signature($Signature);
15151 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015152 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015153 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015154 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015155 $Part=~s/\A\s+|\s+\Z//g;
15156 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15157 if($Part=~/\([\*]+(\w+)\)/i) {
15158 $ParamName = $1;#func-ptr
15159 }
15160 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15161 $ParamName = $1;
15162 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015163 if(not $ParamName)
15164 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015165 push(@Parts, $Part_Styled);
15166 next;
15167 }
15168 if($ItalicParams and not $TName_Tid{1}{$Part}
15169 and not $TName_Tid{2}{$Part})
15170 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015171 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015172 if($Param_Pos ne ""
15173 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015174 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015175 }
15176 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015177 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015178 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015179 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015180 }
15181 $Part_Styled=~s/,(\w)/, $1/g;
15182 push(@Parts, $Part_Styled);
15183 }
15184 if(@Parts)
15185 {
15186 foreach my $Num (0 .. $#Parts)
15187 {
15188 if($Num==$#Parts)
15189 { # add ")" to the last parameter
15190 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15191 }
15192 elsif(length($Parts[$Num])<=45) {
15193 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15194 }
15195 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015196 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 }
15198 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015199 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015200 }
15201 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015202 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015204 $Signature=~s!\[\]![&#160;]!g;
15205 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015206 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15207 if($SymbolVersion) {
15208 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15209 }
15210 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015211}
15212
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015213sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015214{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015215 my $Signature = $_[0];
15216 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15217 {
15218 $Signature=~s/\A\Q$ShortName\E\(//g;
15219 cut_f_attrs($Signature);
15220 $Signature=~s/\)\Z//;
15221 return ($ShortName, $Signature);
15222 }
15223
15224 # error
15225 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015226}
15227
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015228sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015229{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015230 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015232 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15233 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 foreach my $Pos (0 .. length($Params) - 1)
15235 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015236 my $S = substr($Params, $Pos, 1);
15237 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015238 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015239 }
15240 if($S eq "," and
15241 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015242 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015243 if($Comma)
15244 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015245 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015246 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015247 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015248 }
15249 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015250 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015251 }
15252 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015253 if(not $Sp)
15254 { # remove spaces
15255 foreach (@Parts)
15256 {
15257 s/\A //g;
15258 s/ \Z//g;
15259 }
15260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015261 return @Parts;
15262}
15263
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015264sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265{
15266 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015267 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015269 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15270 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271 $Center+=length($1);
15272 }
15273 foreach my $Pos (0 .. length($Sign)-1)
15274 {
15275 my $S = substr($Sign, $Pos, 1);
15276 if($S eq $Target)
15277 {
15278 if($B{"("}==$B{")"}
15279 and $B{"<"}==$B{">"}) {
15280 return $Center;
15281 }
15282 }
15283 if(defined $B{$S}) {
15284 $B{$S}+=1;
15285 }
15286 $Center+=1;
15287 }
15288 return 0;
15289}
15290
15291sub appendFile($$)
15292{
15293 my ($Path, $Content) = @_;
15294 return if(not $Path);
15295 if(my $Dir = get_dirname($Path)) {
15296 mkpath($Dir);
15297 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015298 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015299 print FILE $Content;
15300 close(FILE);
15301}
15302
15303sub writeFile($$)
15304{
15305 my ($Path, $Content) = @_;
15306 return if(not $Path);
15307 if(my $Dir = get_dirname($Path)) {
15308 mkpath($Dir);
15309 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015310 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015311 print FILE $Content;
15312 close(FILE);
15313}
15314
15315sub readFile($)
15316{
15317 my $Path = $_[0];
15318 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015319 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015320 local $/ = undef;
15321 my $Content = <FILE>;
15322 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015323 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015324 $Content=~s/\r/\n/g;
15325 }
15326 return $Content;
15327}
15328
15329sub get_filename($)
15330{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015331 if(defined $Cache{"get_filename"}{$_[0]}) {
15332 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015333 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015334 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15335 return ($Cache{"get_filename"}{$_[0]}=$1);
15336 }
15337 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015338}
15339
15340sub get_dirname($)
15341{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015342 if(defined $Cache{"get_dirname"}{$_[0]}) {
15343 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015344 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015345 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15346 return ($Cache{"get_dirname"}{$_[0]}=$1);
15347 }
15348 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015349}
15350
15351sub separate_path($) {
15352 return (get_dirname($_[0]), get_filename($_[0]));
15353}
15354
15355sub esc($)
15356{
15357 my $Str = $_[0];
15358 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15359 return $Str;
15360}
15361
15362sub readLineNum($$)
15363{
15364 my ($Path, $Num) = @_;
15365 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015366 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015367 foreach (1 ... $Num) {
15368 <FILE>;
15369 }
15370 my $Line = <FILE>;
15371 close(FILE);
15372 return $Line;
15373}
15374
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015375sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015376{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015377 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015378 return () if(not $Path or not -f $Path);
15379 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015380 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15381 {
15382 foreach my $AttrVal (split(/;/, $1))
15383 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015384 if($AttrVal=~/(.+):(.+)/)
15385 {
15386 my ($Name, $Value) = ($1, $2);
15387 $Attributes{$Name} = $Value;
15388 }
15389 }
15390 }
15391 return \%Attributes;
15392}
15393
15394sub is_abs($) {
15395 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15396}
15397
15398sub get_abs_path($)
15399{ # abs_path() should NOT be called for absolute inputs
15400 # because it can change them
15401 my $Path = $_[0];
15402 if(not is_abs($Path)) {
15403 $Path = abs_path($Path);
15404 }
15405 return $Path;
15406}
15407
15408sub get_OSgroup()
15409{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015410 my $N = $Config{"osname"};
15411 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015412 return "macos";
15413 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015414 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015415 return "bsd";
15416 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015417 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015418 return "beos";
15419 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015420 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421 return "symbian";
15422 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015423 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015424 return "windows";
15425 }
15426 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015427 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015428 }
15429}
15430
15431sub getGccVersion($)
15432{
15433 my $LibVersion = $_[0];
15434 if($GCC_VERSION{$LibVersion})
15435 { # dump version
15436 return $GCC_VERSION{$LibVersion};
15437 }
15438 elsif($UsedDump{$LibVersion}{"V"})
15439 { # old-version dumps
15440 return "unknown";
15441 }
15442 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15443 if(not $GccVersion) {
15444 return "unknown";
15445 }
15446 return $GccVersion;
15447}
15448
15449sub showArch($)
15450{
15451 my $Arch = $_[0];
15452 if($Arch eq "arm"
15453 or $Arch eq "mips") {
15454 return uc($Arch);
15455 }
15456 return $Arch;
15457}
15458
15459sub getArch($)
15460{
15461 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015462
15463 if($TargetArch) {
15464 return $TargetArch;
15465 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015466 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015467 { # dump version
15468 return $CPU_ARCH{$LibVersion};
15469 }
15470 elsif($UsedDump{$LibVersion}{"V"})
15471 { # old-version dumps
15472 return "unknown";
15473 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015474
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015475 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015476}
15477
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015478sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015479{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015480 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015481
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015482 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015483 if(getArch(1) ne getArch(2)
15484 or getArch(1) eq "unknown"
15485 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486 { # don't show architecture in the header
15487 $ArchInfo="";
15488 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015489 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015490 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015491 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015492 }
15493 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015494 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015495 }
15496 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015497 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015498 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015499
15500 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15501 {
15502 my $M1 = $UsedDump{1}{"M"};
15503 my $M2 = $UsedDump{2}{"M"};
15504
15505 if($M1 eq $M2)
15506 {
15507 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15508 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15509 }
15510 else
15511 {
15512 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15513 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15514 }
15515 }
15516 else
15517 {
15518 $Title .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent";
15519 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15520 }
15521
15522 $Title .= $ArchInfo;
15523
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015524 if($AppPath) {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015525 $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 +040015526 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015527 $Title = "<h1>".$Title."</h1>\n";
15528 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529}
15530
15531sub get_SourceInfo()
15532{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015533 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015534 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015536 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015537 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015538 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15539 $CheckedHeaders .= "<div class='h_list'>\n";
15540 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15541 {
15542 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15543 my $Name = get_filename($Identity);
15544 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15545 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15546 }
15547 $CheckedHeaders .= "</div>\n";
15548 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015549 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015550
15551 if(my @Sources = keys(%{$Registered_Sources{1}}))
15552 {
15553 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15554 $CheckedSources .= "<div class='h_list'>\n";
15555 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15556 {
15557 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15558 my $Name = get_filename($Identity);
15559 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15560 $CheckedSources .= $Name.$Comment."<br/>\n";
15561 }
15562 $CheckedSources .= "</div>\n";
15563 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015565 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015566 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015567 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015568 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015569 $CheckedLibs .= "<div class='lib_list'>\n";
15570 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15571 {
15572 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15573 $CheckedLibs .= $Library."<br/>\n";
15574 }
15575 $CheckedLibs .= "</div>\n";
15576 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015577 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015578 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15579}
15580
15581sub get_ObjTitle()
15582{
15583 if(defined $UsedDump{1}{"DWARF"}) {
15584 return "Objects";
15585 }
15586 else {
15587 return ucfirst($SLIB_TYPE)." Libraries";
15588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015589}
15590
15591sub get_TypeProblems_Count($$$)
15592{
15593 my ($TypeChanges, $TargetPriority, $Level) = @_;
15594 my $Type_Problems_Count = 0;
15595 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15596 {
15597 my %Kinds_Target = ();
15598 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15599 {
15600 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15601 {
15602 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015603 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15604 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015605 if($Kinds_Target{$Kind}{$Target}) {
15606 next;
15607 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015608
15609 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15610 {
15611 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15612 { # select a problem with the highest priority
15613 next;
15614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015615 }
15616 $Kinds_Target{$Kind}{$Target} = 1;
15617 $Type_Problems_Count += 1;
15618 }
15619 }
15620 }
15621 return $Type_Problems_Count;
15622}
15623
15624sub get_Summary($)
15625{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015626 my $Level = $_[0];
15627 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015628 $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 +040015629 %{$RESULT{$Level}} = (
15630 "Problems"=>0,
15631 "Warnings"=>0,
15632 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015633 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015634 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015636 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015637 {
15638 if(not defined $CompatRules{$Level}{$Kind})
15639 { # unknown rule
15640 if(not $UnknownRules{$Level}{$Kind})
15641 { # only one warning
15642 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15643 $UnknownRules{$Level}{$Kind}=1;
15644 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015645 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015646 }
15647 }
15648 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015649 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15650 {
15651 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15652 {
15653 if(not defined $CompatRules{$Level}{$Kind})
15654 { # unknown rule
15655 if(not $UnknownRules{$Level}{$Kind})
15656 { # only one warning
15657 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15658 $UnknownRules{$Level}{$Kind}=1;
15659 }
15660 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15661 }
15662 }
15663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015664 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015665 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015666 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015667 {
15668 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15669 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015670 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015671 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015672 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015673 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015674 $Added += 1;
15675 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015676 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015677 {
15678 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015679 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015680 }
15681 else
15682 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015683 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 $I_Other += 1;
15685 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015686 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015687 $I_Problems_High += 1;
15688 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015689 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 $I_Problems_Medium += 1;
15691 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015692 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015693 $I_Problems_Low += 1;
15694 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015695 if(($Severity ne "Low" or $StrictCompat)
15696 and $Severity ne "Safe") {
15697 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015698 }
15699 }
15700 }
15701 }
15702 }
15703 }
15704 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015705 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015706 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015707 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015708 {
15709 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15710 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015711 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015712 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015713 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15714 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015715 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015716 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15717
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015718 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015719 { # select a problem with the highest priority
15720 next;
15721 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015722
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015723 if(($Severity ne "Low" or $StrictCompat)
15724 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015725 {
15726 if(defined $TotalAffected{$Level}{$Interface})
15727 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015728 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15729 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015730 }
15731 }
15732 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015733 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015736
15737 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15738
15739 if($MaxSeverity)
15740 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015741 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15742 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015743 }
15744 }
15745 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015746 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015748 }
15749 }
15750 }
15751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015752
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015753 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15754 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15755 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15756 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015757
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015758 %TypeChanges = (); # free memory
15759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015760 if($CheckObjectsOnly)
15761 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015762 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015763 }
15764 else
15765 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015766 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015767 if($ExtendedCheck)
15768 { # don't count external_func_0 for constants
15769 $SCount-=1;
15770 }
15771 if($SCount)
15772 {
15773 my %Weight = (
15774 "High" => 100,
15775 "Medium" => 50,
15776 "Low" => 25
15777 );
15778 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015779 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015781 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782 }
15783 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015784 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015785 }
15786 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015787 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15788 if($RESULT{$Level}{"Affected"}>=100) {
15789 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015790 }
15791
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015792 $RESULT{$Level}{"Problems"} += $Removed;
15793 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015794 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015795 if($StrictCompat) {
15796 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15797 }
15798 else {
15799 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015801
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015802 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015803 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015804 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015805 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015806 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015807 if($Severity eq "Safe")
15808 {
15809 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015810 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015811 elsif($Severity eq "Low")
15812 {
15813 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015814 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015815 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015816 }
15817
15818 if($C_Problems_Low)
15819 {
15820 if($StrictCompat) {
15821 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15822 }
15823 else {
15824 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015825 }
15826 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015827 if($RESULT{$Level}{"Problems"}
15828 and $RESULT{$Level}{"Affected"}) {
15829 $RESULT{$Level}{"Verdict"} = "incompatible";
15830 }
15831 else {
15832 $RESULT{$Level}{"Verdict"} = "compatible";
15833 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015834
15835 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15836 if(not $TotalTypes)
15837 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015838 $TotalTypes = keys(%{$TName_Tid{1}});
15839 }
15840
15841 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15842 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15843
15844 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15845
15846 if($ReportFormat eq "xml")
15847 { # XML
15848 # test info
15849 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15850 $TestInfo .= " <version1>\n";
15851 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015852 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015853 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15854 $TestInfo .= " </version1>\n";
15855
15856 $TestInfo .= " <version2>\n";
15857 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015858 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015859 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15860 $TestInfo .= " </version2>\n";
15861 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15862
15863 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015864 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015865 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015866 $TestResults .= " <headers>\n";
15867 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15868 {
15869 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15870 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15871 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15872 }
15873 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015874 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015875
15876 if(my @Sources = keys(%{$Registered_Sources{1}}))
15877 {
15878 $TestResults .= " <sources>\n";
15879 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15880 {
15881 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15882 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15883 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15884 }
15885 $TestResults .= " </sources>\n";
15886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015887
15888 $TestResults .= " <libs>\n";
15889 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15890 {
15891 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15892 $TestResults .= " <name>$Library</name>\n";
15893 }
15894 $TestResults .= " </libs>\n";
15895
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015896 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015897 $TestResults .= " <types>".$TotalTypes."</types>\n";
15898
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015899 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15900 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015901 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15902
15903 # problem summary
15904 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15905 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15906
15907 $Problem_Summary .= " <problems_with_types>\n";
15908 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15909 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15910 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15911 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15912 $Problem_Summary .= " </problems_with_types>\n";
15913
15914 $Problem_Summary .= " <problems_with_symbols>\n";
15915 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15916 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15917 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015918 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015919 $Problem_Summary .= " </problems_with_symbols>\n";
15920
15921 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015922 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015923 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015924
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015925 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15926
15927 return ($TestInfo.$TestResults.$Problem_Summary, "");
15928 }
15929 else
15930 { # HTML
15931 # test info
15932 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015933 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015934 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15935
15936 my (@VInf1, @VInf2, $AddTestInfo) = ();
15937 if($Arch1 ne "unknown"
15938 and $Arch2 ne "unknown")
15939 { # CPU arch
15940 if($Arch1 eq $Arch2)
15941 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015942 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015943 }
15944 else
15945 { # go to the version number
15946 push(@VInf1, showArch($Arch1));
15947 push(@VInf2, showArch($Arch2));
15948 }
15949 }
15950 if($GccV1 ne "unknown"
15951 and $GccV2 ne "unknown"
15952 and $OStarget ne "windows")
15953 { # GCC version
15954 if($GccV1 eq $GccV2)
15955 { # go to the separate section
15956 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15957 }
15958 else
15959 { # go to the version number
15960 push(@VInf1, "gcc ".$GccV1);
15961 push(@VInf2, "gcc ".$GccV2);
15962 }
15963 }
15964 # show long version names with GCC version and CPU architecture name (if different)
15965 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15966 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15967 $TestInfo .= $AddTestInfo;
15968 #if($COMMON_LANGUAGE{1}) {
15969 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15970 #}
15971 if($ExtendedCheck) {
15972 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015974 if($JoinReport)
15975 {
15976 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015977 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015978 }
15979 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015980 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015981 }
15982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015983 $TestInfo .= "</table>\n";
15984
15985 # test results
15986 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015987 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015988
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015989 if(my @Headers = keys(%{$Registered_Headers{1}}))
15990 {
15991 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15992 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15993 }
15994 elsif($CheckObjectsOnly) {
15995 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15996 }
15997
15998 if(my @Sources = keys(%{$Registered_Sources{1}}))
15999 {
16000 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16001 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016003
16004 if(not $ExtendedCheck)
16005 {
16006 my $Libs_Link = "0";
16007 $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 +040016008 $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 +040016009 }
16010
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016011 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016012
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016013 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 if($JoinReport) {
16015 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16016 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016017 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016018 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016019 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16020 }
16021 else {
16022 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16023 }
16024 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016025 $TestResults .= "</table>\n";
16026
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016027 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016028 # problem summary
16029 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016030 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016031 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16032
16033 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016034 if($Added>0)
16035 {
16036 if($JoinReport) {
16037 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16038 }
16039 else {
16040 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16041 }
16042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016043 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016044 $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 +040016045
16046 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016047 if($Removed>0)
16048 {
16049 if($JoinReport) {
16050 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16051 }
16052 else {
16053 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16054 }
16055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016056 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016057 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16058 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016059
16060 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016061 $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 +040016062 $TH_Link = "n/a" if($CheckObjectsOnly);
16063 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016064 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16065 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016066
16067 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016068 $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 +040016069 $TM_Link = "n/a" if($CheckObjectsOnly);
16070 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016071 $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 +040016072
16073 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016074 $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 +040016075 $TL_Link = "n/a" if($CheckObjectsOnly);
16076 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016077 $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 +040016078
16079 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016080 $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 +040016081 $IH_Link = "n/a" if($CheckObjectsOnly);
16082 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016083 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16084 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016085
16086 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016087 $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 +040016088 $IM_Link = "n/a" if($CheckObjectsOnly);
16089 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016090 $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 +040016091
16092 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016093 $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 +040016094 $IL_Link = "n/a" if($CheckObjectsOnly);
16095 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016096 $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 +040016097
16098 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016099 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16100 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016101 }
16102 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016103 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016104 $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 +040016105
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016106 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016107 if($T_Other and not $CheckObjectsOnly)
16108 {
16109 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016110 $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 +040016111 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016112
16113 if($I_Other and not $CheckObjectsOnly)
16114 {
16115 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016116 $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 +040016117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016118
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016119 if($C_Other and not $CheckObjectsOnly)
16120 {
16121 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16122 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16123 }
16124
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016125 $META_DATA .= "tool_version:$TOOL_VERSION";
16126 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016127 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016128 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16129 }
16130}
16131
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016132sub getStyle($$$)
16133{
16134 my ($Subj, $Act, $Num) = @_;
16135 my %Style = (
16136 "A"=>"new",
16137 "R"=>"failed",
16138 "S"=>"passed",
16139 "L"=>"warning",
16140 "M"=>"failed",
16141 "H"=>"failed"
16142 );
16143 if($Num>0) {
16144 return " class='".$Style{$Act}."'";
16145 }
16146 return "";
16147}
16148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016149sub show_number($)
16150{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016153 my $Num = cut_off_number($_[0], 2, 0);
16154 if($Num eq "0")
16155 {
16156 foreach my $P (3 .. 7)
16157 {
16158 $Num = cut_off_number($_[0], $P, 1);
16159 if($Num ne "0") {
16160 last;
16161 }
16162 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016163 }
16164 if($Num eq "0") {
16165 $Num = $_[0];
16166 }
16167 return $Num;
16168 }
16169 return $_[0];
16170}
16171
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016173{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016174 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016175 if($num!~/\./)
16176 {
16177 $num .= ".";
16178 foreach (1 .. $digs_to_cut-1) {
16179 $num .= "0";
16180 }
16181 }
16182 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16183 {
16184 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16185 $num .= "0";
16186 }
16187 }
16188 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16189 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16190 }
16191 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016192 if($z) {
16193 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 return $num;
16196}
16197
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016198sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016199{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016200 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016201 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016202
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016203 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016204 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16205 {
16206 my $Header = $Constants{1}{$Constant}{"Header"};
16207 if(not $Header)
16208 { # added
16209 $Header = $Constants{2}{$Constant}{"Header"}
16210 }
16211
16212 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16213 {
16214 if(not defined $CompatRules{$Level}{$Kind}) {
16215 next;
16216 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016217 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016218 next;
16219 }
16220 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 if($ReportFormat eq "xml")
16225 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016226 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016227 {
16228 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016229 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230 {
16231 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016232 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16233 {
16234 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16235 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16236 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016237
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016238 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16239 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16240 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016241 if($Overcome) {
16242 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16243 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016244 $CHANGED_CONSTANTS .= " </problem>\n";
16245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016246 $CHANGED_CONSTANTS .= " </constant>\n";
16247 }
16248 $CHANGED_CONSTANTS .= " </header>\n";
16249 }
16250 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16251 }
16252 else
16253 { # HTML
16254 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016255 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 {
16257 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016258 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016259 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016260 my $Report = "";
16261
16262 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16263 {
16264 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16265 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16266 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16267 $Number += 1;
16268 }
16269 if($Report)
16270 {
16271 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16272 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16273 $Report = insertIDs($Report);
16274 }
16275 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016276 }
16277 $CHANGED_CONSTANTS .= "<br/>\n";
16278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016279 if($CHANGED_CONSTANTS)
16280 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016281 my $Title = "Problems with Constants, $TargetSeverity Severity";
16282 if($TargetSeverity eq "Safe")
16283 { # Safe Changes
16284 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016285 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016286 $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 +040016287 }
16288 }
16289 return $CHANGED_CONSTANTS;
16290}
16291
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016292sub getTitle($$$)
16293{
16294 my ($Header, $Library, $NameSpace) = @_;
16295 my $Title = "";
16296 if($Library and $Library!~/\.\w+\Z/) {
16297 $Library .= " (.$LIB_EXT)";
16298 }
16299 if($Header and $Library)
16300 {
16301 $Title .= "<span class='h_name'>$Header</span>";
16302 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16303 }
16304 elsif($Library) {
16305 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16306 }
16307 elsif($Header) {
16308 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16309 }
16310 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016311 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016312 }
16313 return $Title;
16314}
16315
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016316sub get_Report_Added($)
16317{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016318 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016319 my $ADDED_INTERFACES = "";
16320 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016321 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016322 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016323 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016324 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016325 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016326 {
16327 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16328 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016329 if($Level eq "Source" and $ReportFormat eq "html")
16330 { # do not show library name in HTML report
16331 $DyLib = "";
16332 }
16333 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016334 }
16335 }
16336 }
16337 if($ReportFormat eq "xml")
16338 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016339 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016340 {
16341 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016342 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016343 {
16344 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016345 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016346 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16347 }
16348 $ADDED_INTERFACES .= " </library>\n";
16349 }
16350 $ADDED_INTERFACES .= " </header>\n";
16351 }
16352 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16353 }
16354 else
16355 { # HTML
16356 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016357 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016358 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016359 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016360 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016361 my %NameSpaceSymbols = ();
16362 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016363 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016365 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016367 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16368 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016369 foreach my $Interface (@SortedInterfaces)
16370 {
16371 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016372 my $Signature = get_Signature($Interface, 2);
16373 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016374 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016376 if($Interface=~/\A(_Z|\?)/)
16377 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016378 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016379 $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 +040016380 }
16381 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016382 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 }
16384 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016385 else
16386 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016387 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016388 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016389 }
16390 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016391 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016392 }
16393 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016395 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 }
16398 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016399 if($ADDED_INTERFACES)
16400 {
16401 my $Anchor = "<a name='Added'></a>";
16402 if($JoinReport) {
16403 $Anchor = "<a name='".$Level."_Added'></a>";
16404 }
16405 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016406 }
16407 }
16408 return $ADDED_INTERFACES;
16409}
16410
16411sub get_Report_Removed($)
16412{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016413 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016414 my $REMOVED_INTERFACES = "";
16415 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016416 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016417 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016418 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016419 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016422 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16423 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016424 if($Level eq "Source" and $ReportFormat eq "html")
16425 { # do not show library name in HTML report
16426 $DyLib = "";
16427 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016428 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016429 }
16430 }
16431 }
16432 if($ReportFormat eq "xml")
16433 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016434 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 {
16436 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016437 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016438 {
16439 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016440 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16441 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016442 }
16443 $REMOVED_INTERFACES .= " </library>\n";
16444 }
16445 $REMOVED_INTERFACES .= " </header>\n";
16446 }
16447 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16448 }
16449 else
16450 { # HTML
16451 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016452 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016456 my %NameSpaceSymbols = ();
16457 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016458 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016459 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016460 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016461 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016462 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16463 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016464 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 {
16466 $Removed_Number += 1;
16467 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016468 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016470 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016472 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016473 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016474 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016475 $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 +040016476 }
16477 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016478 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016479 }
16480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016481 else
16482 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016483 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016484 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 }
16486 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016487 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016488 }
16489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 }
16491 }
16492 $REMOVED_INTERFACES .= "<br/>\n";
16493 }
16494 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016495 if($REMOVED_INTERFACES)
16496 {
16497 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16498 if($JoinReport) {
16499 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16500 }
16501 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016502 }
16503 }
16504 return $REMOVED_INTERFACES;
16505}
16506
16507sub getXmlParams($$)
16508{
16509 my ($Content, $Problem) = @_;
16510 return "" if(not $Content or not $Problem);
16511 my %XMLparams = ();
16512 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16513 {
16514 my $Macro = "\@".lc($Attr);
16515 if($Content=~/\Q$Macro\E/) {
16516 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16517 }
16518 }
16519 my @PString = ();
16520 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016521 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016522 }
16523 if(@PString) {
16524 return " ".join(" ", @PString);
16525 }
16526 else {
16527 return "";
16528 }
16529}
16530
16531sub addMarkup($)
16532{
16533 my $Content = $_[0];
16534 # auto-markup
16535 $Content=~s/\n[ ]*//; # spaces
16536 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16537 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016538 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016539 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16540 if($Content=~/\ANOTE:/)
16541 { # notes
16542 $Content=~s!(NOTE):!<b>$1</b>:!g;
16543 }
16544 else {
16545 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16546 }
16547 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16548 my @Keywords = (
16549 "void",
16550 "const",
16551 "static",
16552 "restrict",
16553 "volatile",
16554 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016555 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016556 );
16557 my $MKeys = join("|", @Keywords);
16558 foreach (@Keywords) {
16559 $MKeys .= "|non-".$_;
16560 }
16561 $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 +040016562
16563 # Markdown
16564 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16565 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016566 return $Content;
16567}
16568
16569sub applyMacroses($$$$)
16570{
16571 my ($Level, $Kind, $Content, $Problem) = @_;
16572 return "" if(not $Content or not $Problem);
16573 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16574 $Content = addMarkup($Content);
16575 # macros
16576 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16577 {
16578 my $Macro = "\@".lc($Attr);
16579 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016580 if(not defined $Value
16581 or $Value eq "") {
16582 next;
16583 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016584 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016585 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016586 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16587 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016588 $Value = black_name($Value);
16589 }
16590 elsif($Value=~/\s/) {
16591 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16592 }
16593 elsif($Value=~/\A\d+\Z/
16594 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16595 { # bits to bytes
16596 if($Value % $BYTE_SIZE)
16597 { # bits
16598 if($Value==1) {
16599 $Value = "<b>".$Value."</b> bit";
16600 }
16601 else {
16602 $Value = "<b>".$Value."</b> bits";
16603 }
16604 }
16605 else
16606 { # bytes
16607 $Value /= $BYTE_SIZE;
16608 if($Value==1) {
16609 $Value = "<b>".$Value."</b> byte";
16610 }
16611 else {
16612 $Value = "<b>".$Value."</b> bytes";
16613 }
16614 }
16615 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016616 else
16617 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 $Value = "<b>".htmlSpecChars($Value)."</b>";
16619 }
16620 $Content=~s/\Q$Macro\E/$Value/g;
16621 }
16622
16623 if($Content=~/(\A|[^\@\w])\@\w/)
16624 {
16625 if(not $IncompleteRules{$Level}{$Kind})
16626 { # only one warning
16627 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16628 $IncompleteRules{$Level}{$Kind} = 1;
16629 }
16630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016631 return $Content;
16632}
16633
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016634sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016636 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016637 my $INTERFACE_PROBLEMS = "";
16638 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016639
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016640 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016642 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16643 if($SV and defined $CompatProblems{$Level}{$SN}) {
16644 next;
16645 }
16646 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016647 {
16648 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016649 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016651 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16652 my $DyLib = $Symbol_Library{1}{$Symbol};
16653 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 { # Symbol with Version
16655 $DyLib = $Symbol_Library{1}{$VSym};
16656 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016657 if(not $DyLib)
16658 { # const global data
16659 $DyLib = "";
16660 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016661 if($Level eq "Source" and $ReportFormat eq "html")
16662 { # do not show library name in HTML report
16663 $DyLib = "";
16664 }
16665 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16666 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016668 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16669 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016670 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016671 }
16672 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016673 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16674 {
16675 delete($SymbolChanges{$Symbol}{$Kind});
16676 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016678 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016679 }
16680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 if(not keys(%{$SymbolChanges{$Symbol}})) {
16682 delete($SymbolChanges{$Symbol});
16683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016684 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016685
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016686 if($ReportFormat eq "xml")
16687 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016688 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016689 {
16690 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016691 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 {
16693 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016694 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16695 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016696 {
16697 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16698 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16699 {
16700 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16701 {
16702 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016703 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016704
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016705 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16706 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16707 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16708 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16709 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016710 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16711 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 $INTERFACE_PROBLEMS .= " </problem>\n";
16714 }
16715 }
16716 $INTERFACE_PROBLEMS .= " </symbol>\n";
16717 }
16718 $INTERFACE_PROBLEMS .= " </library>\n";
16719 }
16720 $INTERFACE_PROBLEMS .= " </header>\n";
16721 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 }
16724 else
16725 { # HTML
16726 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016727 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016728 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016729 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016730 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016731 my (%NameSpaceSymbols, %NewSignature) = ();
16732 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016733 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016735 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016736 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016737 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016738 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 +040016739 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016740 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016741 my $Signature = get_Signature($Symbol, 1);
16742 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016743 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016744 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016746 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016747 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016748 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016749 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016750 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016751 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016752 }
16753 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16754 {
16755 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016756 $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 +040016757 $ProblemNum += 1;
16758 $ProblemsNum += 1;
16759 }
16760 }
16761 }
16762 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016763 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016764 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016765 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016766 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016767 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 }
16769 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016770 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016771 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016772 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16773 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16774 if($NewSignature{$Symbol})
16775 { # argument list changed to
16776 $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 +040016777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016778 if($Symbol=~/\A(_Z|\?)/) {
16779 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16780 }
16781 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16782 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016783 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016784 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016785 }
16786 }
16787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016788 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016789 }
16790 }
16791 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016792
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016793 if($INTERFACE_PROBLEMS)
16794 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016795 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16796 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16797 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016798 { # Safe Changes
16799 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016800 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016801 $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 +040016802 }
16803 }
16804 return $INTERFACE_PROBLEMS;
16805}
16806
16807sub get_Report_TypeProblems($$)
16808{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016809 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016810 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016811 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016812
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016815 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016816 {
16817 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16818 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016819 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016820 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016821 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016822 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016823 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016824
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016825 if($Severity eq "Safe"
16826 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016827 next;
16828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016829
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016830 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16831 {
16832 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16833 { # select a problem with the highest priority
16834 next;
16835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016836 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016837
16838 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016839 }
16840 }
16841 }
16842 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016843
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016844 my %Kinds_Locations = ();
16845 foreach my $TypeName (keys(%TypeChanges))
16846 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016847 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016848 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16849 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016850 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016851 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016852 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016853 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016854 { # other priority
16855 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16856 next;
16857 }
16858 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16859 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016860 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016861 { # duplicate target
16862 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16863 next;
16864 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016865 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016866 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016867 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 }
16869 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16870 delete($TypeChanges{$TypeName}{$Kind});
16871 }
16872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 if(not keys(%{$TypeChanges{$TypeName}})) {
16874 delete($TypeChanges{$TypeName});
16875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016876 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016877
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016878 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 +040016879 if($ReportFormat eq "xml")
16880 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 {
16883 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016884 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016886 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16888 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016889 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016890 {
16891 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16892 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16893 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16894 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16895 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16896 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016897 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16898 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900 $TYPE_PROBLEMS .= " </problem>\n";
16901 }
16902 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016903 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016904 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016905 $TYPE_PROBLEMS .= showVTables($TypeName);
16906 }
16907 $TYPE_PROBLEMS .= " </type>\n";
16908 }
16909 $TYPE_PROBLEMS .= " </header>\n";
16910 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016911 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 }
16913 else
16914 { # HTML
16915 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016916 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016917 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016918 my (%NameSpace_Type) = ();
16919 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016920 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016921 }
16922 foreach my $NameSpace (sort keys(%NameSpace_Type))
16923 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016924 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016925 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 +040016926 foreach my $TypeName (@SortedTypes)
16927 {
16928 my $ProblemNum = 1;
16929 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016930
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16932 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016933 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016934 {
16935 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16936 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16937 {
16938 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16939 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16940 $ProblemNum += 1;
16941 $ProblemsNum += 1;
16942 }
16943 }
16944 }
16945 $ProblemNum -= 1;
16946 if($TYPE_REPORT)
16947 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016948 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016949 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016950 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016951 $ShowVTables = showVTables($TypeName);
16952 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016953
16954 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16956 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16957 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16958 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016959 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016960 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 }
16962 }
16963 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016964 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016965 }
16966 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016967
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016968 if($TYPE_PROBLEMS)
16969 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016970 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16971 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016972 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016973 { # Safe Changes
16974 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016976 $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 +040016977 }
16978 }
16979 return $TYPE_PROBLEMS;
16980}
16981
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016982sub show_Type($$$)
16983{
16984 my ($Name, $Html, $LibVersion) = @_;
16985 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16986 $TType = lc($TType);
16987 if($TType=~/struct|union|enum/) {
16988 $Name=~s/\A\Q$TType\E //g;
16989 }
16990 if($Html) {
16991 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16992 }
16993 else {
16994 $Name = $TType." ".$Name;
16995 }
16996 return $Name;
16997}
16998
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016999sub get_Anchor($$$)
17000{
17001 my ($Kind, $Level, $Severity) = @_;
17002 if($JoinReport)
17003 {
17004 if($Severity eq "Safe") {
17005 return "Other_".$Level."_Changes_In_".$Kind."s";
17006 }
17007 else {
17008 return $Kind."_".$Level."_Problems_".$Severity;
17009 }
17010 }
17011 else
17012 {
17013 if($Severity eq "Safe") {
17014 return "Other_Changes_In_".$Kind."s";
17015 }
17016 else {
17017 return $Kind."_Problems_".$Severity;
17018 }
17019 }
17020}
17021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017022sub showVTables($)
17023{
17024 my $TypeName = $_[0];
17025 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017026 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017027 if(defined $Type1{"VTable"}
17028 and keys(%{$Type1{"VTable"}}))
17029 {
17030 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017031 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 if(defined $Type2{"VTable"}
17033 and keys(%{$Type2{"VTable"}}))
17034 {
17035 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17036 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017037 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017038 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017039 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17040 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017041 }
17042 my $VTABLES = "";
17043 if($ReportFormat eq "xml")
17044 { # XML
17045 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017046 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017048 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017049 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17050 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017051 $VTABLES .= " </entry>\n";
17052 }
17053 $VTABLES .= " </vtable>\n\n";
17054 }
17055 else
17056 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017057 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017058 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17059 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17060 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017061 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017062 {
17063 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017064 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017066 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017068 $Color1 = " class='failed'";
17069 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017070 }
17071 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017072 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017073 }
17074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017075 $VTABLES .= "<tr><th>".$Index."</th>\n";
17076 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17077 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 }
17079 $VTABLES .= "</table><br/>\n";
17080 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017081 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017082 }
17083 return $VTABLES;
17084 }
17085 }
17086 return "";
17087}
17088
17089sub simpleVEntry($)
17090{
17091 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017092 if(not defined $VEntry
17093 or $VEntry eq "") {
17094 return "";
17095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017096 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17097 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17098 if($VEntry=~/\A_ZThn.+\Z/) {
17099 $VEntry = "non-virtual thunk";
17100 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017101 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017102 # support for old GCC versions
17103 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17104 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17105 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017106 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17107 return $VEntry;
17108}
17109
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017110sub adjustParamPos($$$)
17111{
17112 my ($Pos, $Symbol, $LibVersion) = @_;
17113 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17114 {
17115 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17116 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17117 {
17118 return $Pos-1;
17119 }
17120
17121 return $Pos;
17122 }
17123
17124 return undef;
17125}
17126
17127sub getParamPos($$$)
17128{
17129 my ($Name, $Symbol, $LibVersion) = @_;
17130
17131 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17132 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17133 {
17134 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17135 foreach (keys(%{$Info->{"Param"}}))
17136 {
17137 if($Info->{"Param"}{$_}{"name"} eq $Name)
17138 {
17139 return $_;
17140 }
17141 }
17142 }
17143
17144 return undef;
17145}
17146
17147sub getParamName($)
17148{
17149 my $Loc = $_[0];
17150 $Loc=~s/\->.*//g;
17151 return $Loc;
17152}
17153
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017154sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017156 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017157 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017158
17159 if(defined $AffectLimit)
17160 {
17161 $LIMIT = $AffectLimit;
17162 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017163
17164 my %SymSel = ();
17165 my %SymLocKind = ();
17166
17167 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017168 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017169 if(index($Symbol, "_Z")==0
17170 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017171 { # duplicated problems for C2 constructors, D2 and D0 destructors
17172 next;
17173 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017174
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017175 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017177 if(not defined $CompatProblems{$Level}{$Symbol}
17178 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17179 next;
17180 }
17181
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017182 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017183 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017184 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017185 next;
17186 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017187
17188 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17189 if($Level eq "Source")
17190 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017191 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017192 }
17193
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017194 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017195 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017196 { # duplicated problems for versioned symbols
17197 next;
17198 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017199
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017200 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017201 if($Type_Name ne $Target_TypeName) {
17202 next;
17203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017204
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017205 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017206 }
17207 }
17208 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017209
17210 foreach my $Symbol (sort keys(%SymLocKind))
17211 {
17212 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17213 {
17214 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17215 {
17216 $SymSel{$Symbol}{"Loc"} = $Loc;
17217 $SymSel{$Symbol}{"Kind"} = $Kind;
17218
17219 last LOOP;
17220 }
17221 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017222 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017224 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017225 my $Num = 0;
17226
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017227 if($ReportFormat eq "xml")
17228 { # XML
17229 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017230
17231 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017232 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017233 my $PName = getParamName($Loc);
17234 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017236 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017237 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017238 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017239 $Target .= " param=\"$PName\"";
17240 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017242 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017243 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017244 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017245 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017246 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017247 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017248
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017249 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017250 $Target .= " field=\"$1\"";
17251 }
17252
17253 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017254 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017255 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017256
17257 if($Num>$LIMIT) {
17258 last LOOP;
17259 }
17260
17261 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017262 }
17263 $Affected .= " </affected>\n";
17264 }
17265 else
17266 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017267 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017268 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017269 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17270 my $S = get_Signature($Symbol, 1);
17271 my $PName = getParamName($SymSel{$Symbol}{"Loc"});print "$Symbol\n" if($Symbol eq "sftp_file_set_blocking");
17272 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17273
17274 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17275 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17276
17277 if($Num>$LIMIT) {
17278 last;
17279 }
17280
17281 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017282 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017283
17284 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017285 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017286 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017287
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017288 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017289 if($Affected)
17290 {
17291 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017292 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 }
17294 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 return $Affected;
17297}
17298
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017299sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017300{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017301 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017302 if($L2=~/\A(retval|this)\b/
17303 and $L1!~/\A(retval|this)\b/)
17304 {
17305 if($L1!~/\-\>/) {
17306 return 1;
17307 }
17308 elsif($L2=~/\-\>/) {
17309 return 1;
17310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017311 }
17312 return 0;
17313}
17314
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017315sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017316{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017317 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017318
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017319 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017320
17321 my $Location_I = $Location;
17322 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17323
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017324 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017325
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 if($Kind eq "Overridden_Virtual_Method"
17327 or $Kind eq "Overridden_Virtual_Method_B") {
17328 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17329 }
17330 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17331 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017332 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17333
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17335 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017336 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17337 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017339 if($ClassName eq $Problem{"Type_Name"}) {
17340 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17341 }
17342 else {
17343 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17344 }
17345 }
17346 else
17347 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017348 my $TypeID = undef;
17349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017350 if($Location=~/retval/)
17351 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017352 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017353 push(@Sentence, "Field \'".$Location."\' in return value");
17354 }
17355 else {
17356 push(@Sentence, "Return value");
17357 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017358
17359 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017360 }
17361 elsif($Location=~/this/)
17362 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017363 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017364 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17365 }
17366 else {
17367 push(@Sentence, "\'this\' pointer");
17368 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017369
17370 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017371 }
17372 else
17373 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017374
17375 my $PName = getParamName($Location);
17376 my $PPos = getParamPos($PName, $Symbol, 1);
17377
17378 if(index($Location, "->")!=-1) {
17379 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380 }
17381 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017382 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017383 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017384 if($PName) {
17385 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017386 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017387
17388 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17389 }
17390
17391 if($Location!~/this/)
17392 {
17393 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017394 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017395 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017396 push(@Sentence, "(pointer)");
17397 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017398 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017399 push(@Sentence, "(reference)");
17400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 }
17402 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017403
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017404 if($Location eq "this") {
17405 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17406 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017407 else
17408 {
17409 my $Location_T = $Location;
17410 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17411
17412 my $TypeID_Problem = $TypeID;
17413 if($Location_T) {
17414 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17415 }
17416
17417 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17418 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17419 }
17420 else {
17421 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017423 }
17424 }
17425 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017426 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017427 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 +040017428 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017429
17430 my $Sent = join(" ", @Sentence);
17431
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017432 $Sent=~s/->/./g;
17433
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017434 if($ReportFormat eq "xml")
17435 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017436 $Sent=~s/'//g;
17437 }
17438
17439 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017440}
17441
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017442sub getFieldType($$$)
17443{
17444 my ($Location, $TypeId, $LibVersion) = @_;
17445
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017446 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017447
17448 foreach my $Name (@Fields)
17449 {
17450 my %Info = get_BaseType($TypeId, $LibVersion);
17451
17452 foreach my $Pos (keys(%{$Info{"Memb"}}))
17453 {
17454 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17455 {
17456 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17457 last;
17458 }
17459 }
17460 }
17461
17462 return $TypeId;
17463}
17464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465sub get_XmlSign($$)
17466{
17467 my ($Symbol, $LibVersion) = @_;
17468 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17469 my $Report = "";
17470 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17471 {
17472 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017473 my $Type = $Info->{"Param"}{$Pos}{"type"};
17474 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017475 foreach my $Typedef (keys(%ChangedTypedef))
17476 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017477 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17478 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017480 }
17481 $Report .= " <param pos=\"$Pos\">\n";
17482 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017483 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017484 $Report .= " </param>\n";
17485 }
17486 if(my $Return = $Info->{"Return"})
17487 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017488 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017489 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017490 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017491 $Report .= " </retval>\n";
17492 }
17493 return $Report;
17494}
17495
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017496sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017497{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017498 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017499 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017500 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017501 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017502 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17503 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 next;
17505 }
17506 $Report .= " <symbol name=\"$Symbol\">\n";
17507 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017508 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017509 {
17510 if(defined $CompleteSignature{1}{$Symbol}
17511 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17512 {
17513 $P1 = get_XmlSign($Symbol, 1);
17514 $S1 = get_Signature($Symbol, 1);
17515 }
17516 elsif($Symbol=~/\A(_Z|\?)/) {
17517 $S1 = $tr_name{$Symbol};
17518 }
17519 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017520 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017521 {
17522 if(defined $CompleteSignature{2}{$Symbol}
17523 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17524 {
17525 $P2 = get_XmlSign($Symbol, 2);
17526 $S2 = get_Signature($Symbol, 2);
17527 }
17528 elsif($Symbol=~/\A(_Z|\?)/) {
17529 $S2 = $tr_name{$Symbol};
17530 }
17531 }
17532 if($S1)
17533 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017534 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017535 $Report .= $P1;
17536 $Report .= " </old>\n";
17537 }
17538 if($S2 and $S2 ne $S1)
17539 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017540 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017541 $Report .= $P2;
17542 $Report .= " </new>\n";
17543 }
17544 $Report .= " </symbol>\n";
17545 }
17546 $Report .= "</symbols_info>\n";
17547 return $Report;
17548}
17549
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017550sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017551{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017552 my ($Level, $Report) = @_;
17553 if($ReportFormat eq "xml") {
17554 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017555 }
17556 if($StdOut)
17557 { # --stdout option
17558 print STDOUT $Report;
17559 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017560 else
17561 {
17562 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017563 mkpath(get_dirname($RPath));
17564
17565 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17566 print REPORT $Report;
17567 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017568 }
17569}
17570
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017571sub getReport($)
17572{
17573 my $Level = $_[0];
17574 if($ReportFormat eq "xml")
17575 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017576 if($Level eq "Join")
17577 {
17578 my $Report = "<reports>\n";
17579 $Report .= getReport("Binary");
17580 $Report .= getReport("Source");
17581 $Report .= "</reports>\n";
17582 return $Report;
17583 }
17584 else
17585 {
17586 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17587 my ($Summary, $MetaData) = get_Summary($Level);
17588 $Report .= $Summary."\n";
17589 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17590 $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 +040017591
17592 # additional symbols info (if needed)
17593 # $Report .= get_Report_SymbolsInfo($Level);
17594
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017595 $Report .= "</report>\n";
17596 return $Report;
17597 }
17598 }
17599 else
17600 { # HTML
17601 my $CssStyles = readModule("Styles", "Report.css");
17602 my $JScripts = readModule("Scripts", "Sections.js");
17603 if($Level eq "Join")
17604 {
17605 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17606 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017607 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17608 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017609 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17610 my ($BSummary, $BMetaData) = get_Summary("Binary");
17611 my ($SSummary, $SMetaData) = get_Summary("Source");
17612 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 +030017613 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017614 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017615 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17616 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017617 </div>";
17618 $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>";
17619 $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 Ponomarenko9927e332012-10-19 10:50:48 +040017620 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017621 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017622 return $Report;
17623 }
17624 else
17625 {
17626 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017627 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17628 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17629 my $Description = "$Level compatibility report for the ".$TargetLibraryFName." ".$TargetComponent." between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017630 if($Level eq "Binary")
17631 {
17632 if(getArch(1) eq getArch(2)
17633 and getArch(1) ne "unknown") {
17634 $Description .= " on ".showArch(getArch(1));
17635 }
17636 }
17637 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 +030017638 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017639 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17640 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17641 $Report .= get_SourceInfo();
17642 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017643 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017644 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017645 return $Report;
17646 }
17647 }
17648}
17649
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017650sub getLegend()
17651{
17652 return "<br/>
17653<table class='summary'>
17654<tr>
17655 <td class='new'>added</td>
17656 <td class='passed'>compatible</td>
17657</tr>
17658<tr>
17659 <td class='warning'>warning</td>
17660 <td class='failed'>incompatible</td>
17661</tr></table>\n";
17662}
17663
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017664sub createReport()
17665{
17666 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017667 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017668 writeReport("Join", getReport("Join"));
17669 }
17670 elsif($DoubleReport)
17671 { # default
17672 writeReport("Binary", getReport("Binary"));
17673 writeReport("Source", getReport("Source"));
17674 }
17675 elsif($BinaryOnly)
17676 { # --binary
17677 writeReport("Binary", getReport("Binary"));
17678 }
17679 elsif($SourceOnly)
17680 { # --source
17681 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017682 }
17683}
17684
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017685sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017686{
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017687 my ($LibName, $Single) = @_;
17688 my $Class = "footer";
17689 if(not $Single) {
17690 $Class .= " double_report";
17691 }
17692 my $Footer = "<div class=\'$Class\' align='right'><i>Generated on ".(localtime time);
17693 $Footer .= " by <a href='".$HomePage{"Dev"}."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
17694 $Footer .= "</i></div>";
17695 $Footer .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017696 return $Footer;
17697}
17698
17699sub get_Report_Problems($$)
17700{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017701 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017702
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017703 my $Report = get_Report_TypeProblems($Severity, $Level);
17704 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017705 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017706 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017707
17708 if($Severity eq "Low" or $Severity eq "Safe") {
17709 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017710 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017711
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017712 if($ReportFormat eq "html")
17713 {
17714 if($Report)
17715 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017716 if($JoinReport)
17717 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017718 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017719 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17720 }
17721 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017722 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017725 else
17726 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017727 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017728 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17729 }
17730 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017731 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017732 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017733 }
17734 }
17735 }
17736 return $Report;
17737}
17738
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017739sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017740{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017741 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17742 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17743 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17744 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017745 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17746 <meta name=\"keywords\" content=\"$Keywords\" />
17747 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017748 <title>
17749 $Title
17750 </title>
17751 <style type=\"text/css\">
17752 $Styles
17753 </style>
17754 <script type=\"text/javascript\" language=\"JavaScript\">
17755 <!--
17756 $Scripts
17757 -->
17758 </script>
17759 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017760}
17761
17762sub insertIDs($)
17763{
17764 my $Text = $_[0];
17765 while($Text=~/CONTENT_ID/)
17766 {
17767 if(int($Content_Counter)%2) {
17768 $ContentID -= 1;
17769 }
17770 $Text=~s/CONTENT_ID/c_$ContentID/;
17771 $ContentID += 1;
17772 $Content_Counter += 1;
17773 }
17774 return $Text;
17775}
17776
17777sub checkPreprocessedUnit($)
17778{
17779 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017780 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017781 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017782 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017783
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017784 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017785 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017786 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017787 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017788 chomp($Line);
17789 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017790 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017791 $CurHeader = path_format($1, $OSgroup);
17792 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017793 $CurClass = "";
17794
17795 if(index($CurHeader, $TMP_DIR)==0) {
17796 next;
17797 }
17798
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017799 if(substr($CurHeaderName, 0, 1) eq "<")
17800 { # <built-in>, <command-line>, etc.
17801 $CurHeaderName = "";
17802 $CurHeader = "";
17803 }
17804
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017805 if($ExtraInfo)
17806 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017807 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017808 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17809 }
17810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017811 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017812 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017813 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017814 if($CurHeaderName)
17815 {
17816 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17817 and not $Registered_Headers{$Version}{$CurHeader})
17818 { # not a target
17819 next;
17820 }
17821 if(not is_target_header($CurHeaderName, 1)
17822 and not is_target_header($CurHeaderName, 2))
17823 { # user-defined header
17824 next;
17825 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017826 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017827 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017828
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017829 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017830 {
17831 my ($Name, $Value) = ($1, $2);
17832 if(not $Constants{$Version}{$Name}{"Access"})
17833 {
17834 $Constants{$Version}{$Name}{"Access"} = "public";
17835 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017836 if($CurHeaderName) {
17837 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17838 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017839 }
17840 }
17841 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17842 $Constants{$Version}{$1}{"Access"} = "private";
17843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017844 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017845 else
17846 {
17847 if(defined $ExtraDump)
17848 {
17849 if($Line=~/(\w+)\s*\(/)
17850 { # functions
17851 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17852 }
17853 #elsif($Line=~/(\w+)\s*;/)
17854 #{ # data
17855 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17856 #}
17857 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17858 $CurClass = $2;
17859 }
17860 }
17861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017862 }
17863 close(PREPROC);
17864 foreach my $Constant (keys(%{$Constants{$Version}}))
17865 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017866 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17867 {
17868 delete($Constants{$Version}{$Constant});
17869 next;
17870 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017871 if(not $ExtraDump and ($Constant=~/_h\Z/i
17872 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017873 { # skip
17874 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017875 }
17876 else {
17877 delete($Constants{$Version}{$Constant}{"Access"});
17878 }
17879 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017880 if($Debug)
17881 {
17882 mkpath($DEBUG_PATH{$Version});
17883 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017885}
17886
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017887sub uncoverConstant($$)
17888{
17889 my ($LibVersion, $Constant) = @_;
17890 return "" if(not $LibVersion or not $Constant);
17891 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17892 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17893 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17894 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017895
17896 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017897 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017898 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17899 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017900 {
17901 push(@RecurConstant, $Constant);
17902 my $Uncovered = uncoverConstant($LibVersion, $Value);
17903 if($Uncovered ne "") {
17904 $Value = $Uncovered;
17905 }
17906 pop(@RecurConstant);
17907 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017908
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017909 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017910 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017911 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17912 }
17913 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17914}
17915
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017916sub simpleConstant($$)
17917{
17918 my ($LibVersion, $Value) = @_;
17919 if($Value=~/\W/)
17920 {
17921 my $Value_Copy = $Value;
17922 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17923 {
17924 my $Word = $1;
17925 if($Value!~/$Word\s*\(/)
17926 {
17927 my $Val = uncoverConstant($LibVersion, $Word);
17928 if($Val ne "")
17929 {
17930 $Value=~s/\b$Word\b/$Val/g;
17931 }
17932 }
17933 }
17934 }
17935 return $Value;
17936}
17937
17938sub computeValue($)
17939{
17940 my $Value = $_[0];
17941
17942 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17943 return $1;
17944 }
17945
17946 if($Value=~/\A[\d\-\+()]+\Z/) {
17947 return eval($Value);
17948 }
17949
17950 return $Value;
17951}
17952
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017953my %IgnoreConstant = map {$_=>1} (
17954 "VERSION",
17955 "VERSIONCODE",
17956 "VERNUM",
17957 "VERS_INFO",
17958 "PATCHLEVEL",
17959 "INSTALLPREFIX",
17960 "VBUILD",
17961 "VPATCH",
17962 "VMINOR",
17963 "BUILD_STRING",
17964 "BUILD_TIME",
17965 "PACKAGE_STRING",
17966 "PRODUCTION",
17967 "CONFIGURE_COMMAND",
17968 "INSTALLDIR",
17969 "BINDIR",
17970 "CONFIG_FILE_PATH",
17971 "DATADIR",
17972 "EXTENSION_DIR",
17973 "INCLUDE_PATH",
17974 "LIBDIR",
17975 "LOCALSTATEDIR",
17976 "SBINDIR",
17977 "SYSCONFDIR",
17978 "RELEASE",
17979 "SOURCE_ID",
17980 "SUBMINOR",
17981 "MINOR",
17982 "MINNOR",
17983 "MINORVERSION",
17984 "MAJOR",
17985 "MAJORVERSION",
17986 "MICRO",
17987 "MICROVERSION",
17988 "BINARY_AGE",
17989 "INTERFACE_AGE",
17990 "CORE_ABI",
17991 "PATCH",
17992 "COPYRIGHT",
17993 "TIMESTAMP",
17994 "REVISION",
17995 "PACKAGE_TAG",
17996 "PACKAGEDATE",
17997 "NUMVERSION",
17998 "Release",
17999 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018000);
18001
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018002sub constantFilter($$$)
18003{
18004 my ($Name, $Value, $Level) = @_;
18005
18006 if($Level eq "Binary")
18007 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018008 if($Name=~/_t\Z/)
18009 { # __malloc_ptr_t
18010 return 1;
18011 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018012 foreach (keys(%IgnoreConstant))
18013 {
18014 if($Name=~/(\A|_)$_(_|\Z)/)
18015 { # version
18016 return 1;
18017 }
18018 if(/\A[A-Z].*[a-z]\Z/)
18019 {
18020 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18021 { # version
18022 return 1;
18023 }
18024 }
18025 }
18026 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18027 { # version
18028 return 1;
18029 }
18030 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18031 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18032 return 1;
18033 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018034
18035 if($Value=~/\A["'].*['"]/i)
18036 { # string
18037 return 0;
18038 }
18039
18040 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18041 { # static int gcry_pth_init
18042 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018043 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018044 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018045 return 1;
18046 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018047 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018048 { # foo(p)
18049 return 1;
18050 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018051 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018052 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018053 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018054 return 1;
18055 }
18056 }
18057
18058 return 0;
18059}
18060
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018061sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018062{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018063 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018064 foreach my $Constant (keys(%{$Constants{1}}))
18065 {
18066 if($SkipConstants{1}{$Constant})
18067 { # skipped by the user
18068 next;
18069 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018070
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018071 if(my $Header = $Constants{1}{$Constant}{"Header"})
18072 {
18073 if(not is_target_header($Header, 1)
18074 and not is_target_header($Header, 2))
18075 { # user-defined header
18076 next;
18077 }
18078 }
18079 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018080 next;
18081 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018082
18083 my $Old_Value = uncoverConstant(1, $Constant);
18084
18085 if(constantFilter($Constant, $Old_Value, $Level))
18086 { # separate binary and source problems
18087 next;
18088 }
18089
18090 if(not defined $Constants{2}{$Constant}{"Value"})
18091 { # removed
18092 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18093 "Target"=>$Constant,
18094 "Old_Value"=>$Old_Value );
18095 next;
18096 }
18097
18098 if($Constants{2}{$Constant}{"Value"} eq "")
18099 { # empty value
18100 # TODO: implement a rule
18101 next;
18102 }
18103
18104 my $New_Value = uncoverConstant(2, $Constant);
18105
18106 my $Old_Value_Pure = $Old_Value;
18107 my $New_Value_Pure = $New_Value;
18108
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018109 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18110 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18111 $New_Value_Pure=~s/(\W)\s+/$1/g;
18112 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018114 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018115
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018116 if($New_Value_Pure ne $Old_Value_Pure)
18117 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018118 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18119 { # complex values
18120 next;
18121 }
18122 if(computeValue($Old_Value) eq computeValue($New_Value))
18123 { # expressions
18124 next;
18125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018126 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18127 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18128 next;
18129 }
18130 if($Old_Value eq "0" and $New_Value eq "NULL")
18131 { # 0 => NULL
18132 next;
18133 }
18134 if($Old_Value eq "NULL" and $New_Value eq "0")
18135 { # NULL => 0
18136 next;
18137 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018138 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018139 "Target"=>$Constant,
18140 "Old_Value"=>$Old_Value,
18141 "New_Value"=>$New_Value );
18142 }
18143 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018144
18145 foreach my $Constant (keys(%{$Constants{2}}))
18146 {
18147 if(not defined $Constants{1}{$Constant}{"Value"})
18148 {
18149 if($SkipConstants{2}{$Constant})
18150 { # skipped by the user
18151 next;
18152 }
18153
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018154 if(my $Header = $Constants{2}{$Constant}{"Header"})
18155 {
18156 if(not is_target_header($Header, 1)
18157 and not is_target_header($Header, 2))
18158 { # user-defined header
18159 next;
18160 }
18161 }
18162 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018163 next;
18164 }
18165
18166 my $New_Value = uncoverConstant(2, $Constant);
18167 if(not defined $New_Value or $New_Value eq "") {
18168 next;
18169 }
18170
18171 if(constantFilter($Constant, $New_Value, $Level))
18172 { # separate binary and source problems
18173 next;
18174 }
18175
18176 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18177 "Target"=>$Constant,
18178 "New_Value"=>$New_Value );
18179 }
18180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018181}
18182
18183sub convert_integer($)
18184{
18185 my $Value = $_[0];
18186 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018187 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018188 return hex($Value);
18189 }
18190 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018191 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018192 return oct($Value);
18193 }
18194 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018195 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018196 return oct($Value);
18197 }
18198 else {
18199 return $Value;
18200 }
18201}
18202
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018203sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018204{
18205 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018206 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018207 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018208 {
18209 if($LibVersion==1)
18210 {
18211 printMsg("WARNING", "checking headers only");
18212 $CheckHeadersOnly = 1;
18213 }
18214 else {
18215 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18216 }
18217 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018218
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018219 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018220 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018221 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018222
18223 if($CheckUndefined)
18224 {
18225 my %UndefinedLibs = ();
18226
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018227 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18228
18229 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018230 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018231 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018232 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018233 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018234 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018235 if($Symbol_Library{$LibVersion}{$Symbol}
18236 or $DepSymbol_Library{$LibVersion}{$Symbol})
18237 { # exported by target library
18238 next;
18239 }
18240 if(index($Symbol, '@')!=-1)
18241 { # exported default symbol version (@@)
18242 $Symbol=~s/\@/\@\@/;
18243 if($Symbol_Library{$LibVersion}{$Symbol}
18244 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18245 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018246 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018247 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018248 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18249 $UndefinedLibs{$Path} = 1;
18250 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018251 }
18252 }
18253 }
18254 if($ExtraInfo)
18255 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018256 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018257 {
18258 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018259 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018260 foreach (@Paths)
18261 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018262 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018263 my ($Dir, $Name) = separate_path($_);
18264
18265 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018266 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018267 }
18268
18269 $Name = parse_libname($Name, "name", $OStarget);
18270 $Name=~s/\Alib//;
18271
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018272 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018273 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018274
18275 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18276 {
18277 $LibString = " -L".esc($Dir).$LibString;
18278 }
18279
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018280 writeFile($ExtraInfo."/libs-string", $LibString);
18281 }
18282 }
18283 }
18284
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018285 if($ExtraInfo) {
18286 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18287 }
18288
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018289 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018290 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018291 if($#LibPaths!=-1)
18292 {
18293 if(not keys(%{$Symbol_Library{$LibVersion}}))
18294 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018295 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018296 printMsg("WARNING", "checking headers only");
18297 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018298 }
18299 }
18300 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018301
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018302 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018303 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018304}
18305
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018306my %Prefix_Lib_Map=(
18307 # symbols for autodetecting library dependencies (by prefix)
18308 "pthread_" => ["libpthread"],
18309 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18310 "cairo_" => ["libcairo"],
18311 "gtk_" => ["libgtk-x11-2.0"],
18312 "atk_" => ["libatk-1.0"],
18313 "gdk_" => ["libgdk-x11-2.0"],
18314 "gl" => ["libGL"],
18315 "glu" => ["libGLU"],
18316 "popt" => ["libpopt"],
18317 "Py" => ["libpython"],
18318 "jpeg_" => ["libjpeg"],
18319 "BZ2_" => ["libbz2"],
18320 "Fc" => ["libfontconfig"],
18321 "Xft" => ["libXft"],
18322 "SSL_" => ["libssl"],
18323 "sem_" => ["libpthread"],
18324 "snd_" => ["libasound"],
18325 "art_" => ["libart_lgpl_2"],
18326 "dbus_g" => ["libdbus-glib-1"],
18327 "GOMP_" => ["libgomp"],
18328 "omp_" => ["libgomp"],
18329 "cms" => ["liblcms"]
18330);
18331
18332my %Pattern_Lib_Map=(
18333 "SL[a-z]" => ["libslang"]
18334);
18335
18336my %Symbol_Lib_Map=(
18337 # symbols for autodetecting library dependencies (by name)
18338 "pow" => "libm",
18339 "fmod" => "libm",
18340 "sin" => "libm",
18341 "floor" => "libm",
18342 "cos" => "libm",
18343 "dlopen" => "libdl",
18344 "deflate" => "libz",
18345 "inflate" => "libz",
18346 "move_panel" => "libpanel",
18347 "XOpenDisplay" => "libX11",
18348 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018349 "clock_gettime" => "librt",
18350 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018351);
18352
18353sub find_SymbolLibs($$)
18354{
18355 my ($LibVersion, $Symbol) = @_;
18356
18357 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18358 { # debug symbols
18359 return ();
18360 }
18361
18362 my %Paths = ();
18363
18364 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18365 {
18366 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18367 $Paths{$Path} = 1;
18368 }
18369 }
18370
18371 if(my $SymbolPrefix = getPrefix($Symbol))
18372 {
18373 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18374 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18375 }
18376
18377 if(not keys(%Paths))
18378 {
18379 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18380 {
18381 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18382 {
18383 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18384 $Paths{$Path} = 1;
18385 }
18386 }
18387 }
18388 }
18389
18390 if(not keys(%Paths))
18391 {
18392 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18393 {
18394 if($Symbol=~/\A$Prefix/)
18395 {
18396 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18397 {
18398 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18399 $Paths{$Path} = 1;
18400 }
18401 }
18402 }
18403 }
18404 }
18405
18406 if(not keys(%Paths))
18407 {
18408 if($SymbolPrefix)
18409 { # try to find a library by symbol prefix
18410 if($SymbolPrefix eq "inotify" and
18411 index($Symbol, "\@GLIBC")!=-1)
18412 {
18413 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18414 $Paths{$Path} = 1;
18415 }
18416 }
18417 else
18418 {
18419 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18420 $Paths{$Path} = 1;
18421 }
18422 }
18423 }
18424 }
18425
18426 if(my @Paths = keys(%Paths)) {
18427 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18428 }
18429 }
18430 return keys(%Paths);
18431}
18432
18433sub get_LibPath_Prefix($$)
18434{
18435 my ($LibVersion, $Prefix) = @_;
18436
18437 $Prefix = lc($Prefix);
18438 $Prefix=~s/[_]+\Z//g;
18439
18440 foreach ("-2", "2", "-1", "1", "")
18441 { # libgnome-2.so
18442 # libxml2.so
18443 # libdbus-1.so
18444 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18445 return $Path;
18446 }
18447 }
18448 return "";
18449}
18450
18451sub getPrefix($)
18452{
18453 my $Str = $_[0];
18454 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18455 { # XmuValidArea: Xmu
18456 return $1;
18457 }
18458 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18459 { # snfReadFont: snf
18460 return $1;
18461 }
18462 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18463 { # XRRTimes: XRR
18464 return $1;
18465 }
18466 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18467 { # H5HF_delete: H5
18468 return $1;
18469 }
18470 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18471 { # alarm_event_add: alarm_
18472 return $1;
18473 }
18474 elsif($Str=~/\A(([a-z])\2{1,})/i)
18475 { # ffopen
18476 return $1;
18477 }
18478 return "";
18479}
18480
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018481sub getSymbolSize($$)
18482{ # size from the shared library
18483 my ($Symbol, $LibVersion) = @_;
18484 return 0 if(not $Symbol);
18485 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18486 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18487 {
18488 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18489 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18490 {
18491 if($Size<0) {
18492 return -$Size;
18493 }
18494 }
18495 }
18496 return 0;
18497}
18498
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018499sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018500{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18501 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018502 my ($Name, $Type) = @_;
18503
18504 # single
18505 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018506 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018507 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018508 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018509 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018510
18511 # double
18512 if($Name=~/$DEFAULT_STD_PARMS/)
18513 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018514 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018515 {
18516 my ($ShortName, $FuncParams) = split_Signature($Name);
18517
18518 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18519 {
18520 if(index($FParam, "<")!=-1)
18521 {
18522 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18523 my $FParam_N = canonifyName($FParam, "T");
18524 if($FParam_N ne $FParam) {
18525 $Name=~s/\Q$FParam\E/$FParam_N/g;
18526 }
18527 }
18528 }
18529 }
18530 elsif($Type eq "T")
18531 {
18532 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18533
18534 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018535 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018536 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018537 my $FParam = $TParams[0];
18538 foreach my $Pos (1 .. $#TParams)
18539 {
18540 my $TParam = $TParams[$Pos];
18541 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18542 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18543 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018544 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018545 }
18546 }
18547 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018548 if($Type eq "S") {
18549 return formatName($Name, "S");
18550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018551 return $Name;
18552}
18553
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018554sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018555{
18556 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018557 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018558 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018559 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018560 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018561 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018562 next if($tr_name{$Symbol});
18563 $Symbol=~s/[\@\$]+(.*)\Z//;
18564 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018565 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018566 elsif(index($Symbol, "?")==0)
18567 {
18568 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018569 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018570 }
18571 else
18572 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018573 $tr_name{$Symbol} = $Symbol;
18574 $mangled_name_gcc{$Symbol} = $Symbol;
18575 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018576 }
18577 }
18578 if($#MnglNames1 > -1)
18579 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018580 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018581 foreach my $MnglName (@MnglNames1)
18582 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018583 if(my $Unmangled = pop(@UnmangledNames))
18584 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018585 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018586 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18587 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18588 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018589 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018590 and $tr_name{$MnglName}=~/vtable for (.+)/)
18591 { # bind class name and v-table symbol
18592 my $ClassName = $1;
18593 $ClassVTable{$ClassName} = $MnglName;
18594 $VTableClass{$MnglName} = $ClassName;
18595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018596 }
18597 }
18598 }
18599 if($#MnglNames2 > -1)
18600 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018601 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018602 foreach my $MnglName (@MnglNames2)
18603 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018604 if(my $Unmangled = pop(@UnmangledNames))
18605 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018606 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018607 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018609 }
18610 }
18611 return \%tr_name;
18612}
18613
18614sub link_symbol($$$)
18615{
18616 my ($Symbol, $RunWith, $Deps) = @_;
18617 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18618 return 1;
18619 }
18620 if($Deps eq "+Deps")
18621 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018622 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018623 return 1;
18624 }
18625 }
18626 return 0;
18627}
18628
18629sub link_symbol_internal($$$)
18630{
18631 my ($Symbol, $RunWith, $Where) = @_;
18632 return 0 if(not $Where or not $Symbol);
18633 if($Where->{$RunWith}{$Symbol})
18634 { # the exact match by symbol name
18635 return 1;
18636 }
18637 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18638 { # indirect symbol version, i.e.
18639 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018640 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018641 if($Where->{$RunWith}{$VSym}) {
18642 return 1;
18643 }
18644 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018645 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018646 if($Sym and $Ver)
18647 { # search for the symbol with the same version
18648 # or without version
18649 if($Where->{$RunWith}{$Sym})
18650 { # old: foo@v|foo@@v
18651 # new: foo
18652 return 1;
18653 }
18654 if($Where->{$RunWith}{$Sym."\@".$Ver})
18655 { # old: foo|foo@@v
18656 # new: foo@v
18657 return 1;
18658 }
18659 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18660 { # old: foo|foo@v
18661 # new: foo@@v
18662 return 1;
18663 }
18664 }
18665 return 0;
18666}
18667
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018668sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018669{
18670 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018671 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018672 my @Imported = ();
18673 if($OSgroup eq "macos")
18674 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018675 my $NM = get_CmdPath("nm");
18676 if(not $NM) {
18677 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018678 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018679 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018680 while(<APP>)
18681 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018682 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018683 push(@Imported, $1);
18684 }
18685 }
18686 close(APP);
18687 }
18688 elsif($OSgroup eq "windows")
18689 {
18690 my $DumpBinCmd = get_CmdPath("dumpbin");
18691 if(not $DumpBinCmd) {
18692 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18693 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018694 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018695 while(<APP>)
18696 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018697 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18698 push(@Imported, $1);
18699 }
18700 }
18701 close(APP);
18702 }
18703 else
18704 {
18705 my $ReadelfCmd = get_CmdPath("readelf");
18706 if(not $ReadelfCmd) {
18707 exitStatus("Not_Found", "can't find \"readelf\"");
18708 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018709 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018710 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018711 while(<APP>)
18712 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018713 if(defined $symtab)
18714 { # do nothing with symtab
18715 if(index($_, "'.dynsym'")!=-1)
18716 { # dynamic table
18717 $symtab = undef;
18718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018719 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018720 elsif(index($_, "'.symtab'")!=-1)
18721 { # symbol table
18722 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018723 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018724 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018725 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018726 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18727 if($Ndx eq "UND")
18728 { # only imported symbols
18729 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018730 }
18731 }
18732 }
18733 close(APP);
18734 }
18735 return @Imported;
18736}
18737
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018738my %ELF_BIND = map {$_=>1} (
18739 "WEAK",
18740 "GLOBAL"
18741);
18742
18743my %ELF_TYPE = map {$_=>1} (
18744 "FUNC",
18745 "IFUNC",
18746 "OBJECT",
18747 "COMMON"
18748);
18749
18750my %ELF_VIS = map {$_=>1} (
18751 "DEFAULT",
18752 "PROTECTED"
18753);
18754
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018755sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018756{ # read the line of 'readelf' output corresponding to the symbol
18757 my @Info = split(/\s+/, $_[0]);
18758 # Num: Value Size Type Bind Vis Ndx Name
18759 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018760 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761 shift(@Info); # spaces
18762 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018763
18764 if($#Info==7)
18765 { # UND SYMBOL (N)
18766 if($Info[7]=~/\(\d+\)/) {
18767 pop(@Info);
18768 }
18769 }
18770
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018771 if($#Info!=6)
18772 { # other lines
18773 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018774 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018775 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018776 return () if(not defined $ELF_BIND{$Info[3]});
18777 return () if(not defined $ELF_VIS{$Info[4]});
18778 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18779 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18780 return ();
18781 }
18782 if($OStarget eq "symbian")
18783 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18784 if(index($Info[6], "_._.absent_export_")!=-1)
18785 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18786 return ();
18787 }
18788 $Info[6]=~s/\@.+//g; # remove version
18789 }
18790 if(index($Info[2], "0x") == 0)
18791 { # size == 0x3d158
18792 $Info[2] = hex($Info[2]);
18793 }
18794 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018795}
18796
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018797sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018798{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018799 my ($LibVersion, $Name) = @_;
18800 return "" if(not $LibVersion or not $Name);
18801 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18802 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018803 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018804 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18805}
18806
18807sub get_LibPath_I($$)
18808{
18809 my ($LibVersion, $Name) = @_;
18810 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018811 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018812 if(-f $Name)
18813 { # absolute path
18814 return $Name;
18815 }
18816 else
18817 { # broken
18818 return "";
18819 }
18820 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018821 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018822 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018823 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018824 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018825 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018826 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018827 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018828 }
18829 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18830 { # ldconfig default paths
18831 return $DefaultPath;
18832 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018833 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 { # search in default linker directories
18835 # and then in all system paths
18836 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018837 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018838 }
18839 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018840 if(not defined $Cache{"checkSystemFiles"}) {
18841 checkSystemFiles();
18842 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018843 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18844 return $AllObjects[0];
18845 }
18846 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18847 {
18848 if($ShortName ne $Name)
18849 { # FIXME: check this case
18850 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18851 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018852 }
18853 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018854 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018855 # can't find
18856 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018857}
18858
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018859sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018860{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018861 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18862 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018863
18864 my $Real_Path = realpath($Lib_Path);
18865
18866 if(not $Real_Path)
18867 { # broken link
18868 return ();
18869 }
18870
18871 my $Lib_Name = get_filename($Real_Path);
18872
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018873 if($ExtraInfo)
18874 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018875 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018876 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018877 }
18878
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018879 if($IsNeededLib)
18880 {
18881 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18882 return ();
18883 }
18884 }
18885 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018887
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 push(@RecurLib, $Lib_Name);
18889 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018890 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18891
18892 if(not $IsNeededLib)
18893 { # special cases: libstdc++ and libc
18894 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18895 {
18896 if($ShortName eq "libstdc++")
18897 { # libstdc++.so.6
18898 $STDCXX_TESTING = 1;
18899 }
18900 elsif($ShortName eq "libc")
18901 { # libc-2.11.3.so
18902 $GLIBC_TESTING = 1;
18903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018904 }
18905 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018906 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018907 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018908 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018909 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018910 mkpath(get_dirname($DebugPath));
18911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018912 if($OStarget eq "macos")
18913 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018914 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018915 if(not $NM) {
18916 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018917 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018918 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018919 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018920 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018921 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018922 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018923 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018924 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018925 else
18926 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018927 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018929 while(<LIB>)
18930 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018931 if($CheckUndefined)
18932 {
18933 if(not $IsNeededLib)
18934 {
18935 if(/ U _([\w\$]+)\s*\Z/)
18936 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018937 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018938 next;
18939 }
18940 }
18941 }
18942
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018943 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018944 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018945 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018946 if($IsNeededLib)
18947 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018948 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018949 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018950 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18951 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018953 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018954 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018955 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018956 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18957 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018958 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18959 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018960 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018961 setLanguage($LibVersion, "C++");
18962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018963 }
18964 if($CheckObjectsOnly
18965 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018966 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018967 }
18968 }
18969 }
18970 }
18971 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018972
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018973 if($Deps)
18974 {
18975 if($LIB_TYPE eq "dynamic")
18976 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018977
18978 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018979 if(not $OtoolCmd) {
18980 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018981 }
18982
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018983 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18984 while(<LIB>)
18985 {
18986 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18987 and $1 ne $Lib_Path) {
18988 $NeededLib{$1} = 1;
18989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018990 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018991 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018993 }
18994 }
18995 elsif($OStarget eq "windows")
18996 { # Windows *.dll, *.lib
18997 my $DumpBinCmd = get_CmdPath("dumpbin");
18998 if(not $DumpBinCmd) {
18999 exitStatus("Not_Found", "can't find \"dumpbin\"");
19000 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019001 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019002 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019003 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019004 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019005 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019006 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019007 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019008 else
19009 { # write to pipe
19010 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019012 while(<LIB>)
19013 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19014 # 1198 4AD SetThreadToken (forwarded to ...)
19015 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019016 # 1 0 00005B30 ??0?N = ... (with pdb)
19017 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019018 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019019 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019020 { # dynamic, static and forwarded symbols
19021 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019022 if($IsNeededLib)
19023 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019024 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019025 {
19026 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19027 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019029 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019030 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 {
19032 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19033 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019034 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19035 {
19036 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19037 setLanguage($LibVersion, "C++");
19038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019039 }
19040 if($CheckObjectsOnly
19041 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019042 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019043 }
19044 }
19045 }
19046 }
19047 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019048
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019049 if($Deps)
19050 {
19051 if($LIB_TYPE eq "dynamic")
19052 { # dependencies
19053 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19054 while(<LIB>)
19055 {
19056 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19057 and $1 ne $Lib_Path) {
19058 $NeededLib{path_format($1, $OSgroup)} = 1;
19059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019060 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019061 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019063 }
19064 }
19065 else
19066 { # Unix; *.so, *.a
19067 # Symbian: *.dso, *.lib
19068 my $ReadelfCmd = get_CmdPath("readelf");
19069 if(not $ReadelfCmd) {
19070 exitStatus("Not_Found", "can't find \"readelf\"");
19071 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019072 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019073 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019074 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019075 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019076 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019077 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019078 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019079 else
19080 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019081 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019082 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019083 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019084 while(<LIB>)
19085 {
19086 if($LIB_TYPE eq "dynamic")
19087 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019088 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019089 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019090 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019091 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019092 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019093 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019094 # do nothing with symtab
19095 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019096 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019097 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019098 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019099 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019100 next;
19101 }
19102 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019103 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019104 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019105 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019106 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019107 if($CheckUndefined)
19108 {
19109 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019110 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019111 }
19112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019113 next;
19114 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019115 if($Bind eq "WEAK")
19116 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019117 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019118 if($Weak eq "-Weak")
19119 { # skip WEAK symbols
19120 next;
19121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019122 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019123 my $Short = $Symbol;
19124 $Short=~s/\@.+//g;
19125 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019126 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019127 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19128 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019129 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019130 if($IsNeededLib)
19131 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019132 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019133 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019134 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19135 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019138 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019139 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019140 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19141 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19142 if($Vers)
19143 {
19144 if($LIB_EXT eq "so")
19145 { # value
19146 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19147 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19148 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019149 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019150 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19151 {
19152 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19153 setLanguage($LibVersion, "C++");
19154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019155 }
19156 if($CheckObjectsOnly
19157 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019158 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019159 }
19160 }
19161 }
19162 }
19163 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019164
19165 if($Deps and $LIB_TYPE eq "dynamic")
19166 { # dynamic library specifics
19167 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19168 open(LIB, $Cmd." |");
19169
19170 while(<LIB>)
19171 {
19172 if(/NEEDED.+\[([^\[\]]+)\]/)
19173 { # dependencies:
19174 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19175 $NeededLib{$1} = 1;
19176 }
19177 }
19178
19179 close(LIB);
19180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019182 if($Vers)
19183 {
19184 if(not $IsNeededLib and $LIB_EXT eq "so")
19185 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019186 my %Found = ();
19187
19188 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019189 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019190 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019191 next if(index($Symbol,"\@")==-1);
19192 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019193 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019194 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019195 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019196 if($Symbol_SameValue ne $Symbol
19197 and index($Symbol_SameValue,"\@")==-1)
19198 {
19199 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019200 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019201 last;
19202 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019203 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019204 }
19205 }
19206
19207 # default
19208 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19209 {
19210 next if(defined $Found{$Symbol});
19211 next if(index($Symbol,"\@\@")==-1);
19212
19213 if($Symbol=~/\A([^\@]*)\@\@/
19214 and not $SymVer{$LibVersion}{$1})
19215 {
19216 $SymVer{$LibVersion}{$1} = $Symbol;
19217 $Found{$Symbol} = 1;
19218 }
19219 }
19220
19221 # non-default
19222 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19223 {
19224 next if(defined $Found{$Symbol});
19225 next if(index($Symbol,"\@")==-1);
19226
19227 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19228 and not $SymVer{$LibVersion}{$1})
19229 {
19230 $SymVer{$LibVersion}{$1} = $Symbol;
19231 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 }
19233 }
19234 }
19235 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019236 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019237 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019238 foreach my $DyLib (sort keys(%NeededLib))
19239 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019240 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19241
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019242 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19243 {
19244 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19245 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19246 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019248 }
19249 }
19250 pop(@RecurLib);
19251 return $Library_Symbol{$LibVersion};
19252}
19253
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019254sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019255{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019256 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019257 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019258 return keys(%Prefixes);
19259}
19260
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019261sub get_prefixes_I($$)
19262{
19263 foreach my $P (@{$_[0]})
19264 {
19265 my @Parts = reverse(split(/[\/\\]+/, $P));
19266 my $Name = $Parts[0];
19267 foreach (1 .. $#Parts)
19268 {
19269 $_[1]->{$Name}{$P} = 1;
19270 last if($_>4 or $Parts[$_] eq "include");
19271 $Name = $Parts[$_].$SLASH.$Name;
19272 }
19273 }
19274}
19275
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019276sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019277{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019278 $Cache{"checkSystemFiles"} = 1;
19279
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019280 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019281
19282 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019283 {
19284 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019285
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019286 my @Files = cmd_find($DevelPath,"f");
19287 foreach my $Link (cmd_find($DevelPath,"l"))
19288 { # add symbolic links
19289 if(-f $Link) {
19290 push(@Files, $Link);
19291 }
19292 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019293
19294 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019295 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019296 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019297 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19298 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19299 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019300 }
19301
19302 # search for libraries in /usr/lib (including symbolic links)
19303 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19304 foreach my $Path (@Libs)
19305 {
19306 my $N = get_filename($Path);
19307 $SystemObjects{$N}{$Path} = 1;
19308 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019309 }
19310 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019311
19312 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019313 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019314 foreach my $DevelPath (@{$SystemPaths{"include"}})
19315 {
19316 next if(not -d $DevelPath);
19317 # search for all header files in the /usr/include
19318 # with or without extension (ncurses.h, QtCore, ...)
19319 push(@SysHeaders, cmd_find($DevelPath,"f"));
19320 foreach my $Link (cmd_find($DevelPath,"l"))
19321 { # add symbolic links
19322 if(-f $Link) {
19323 push(@SysHeaders, $Link);
19324 }
19325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019326 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019327 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019328 }
19329}
19330
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019331sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019332{
19333 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019334 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019335 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19336 {
19337 if(not -e $Dest) {
19338 exitStatus("Access_Error", "can't access \'$Dest\'");
19339 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019340 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019341 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19342 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019343 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019344 }
19345 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019346 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019347}
19348
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019349sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019350{
19351 my ($Path, $LibVersion) = @_;
19352 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019353 my $Name = get_filename($Path);
19354 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019355 return 1;
19356 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019357 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019358 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19359 return 1;
19360 }
19361 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19362 {
19363 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19364 return 1;
19365 }
19366 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019367 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019368 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019369 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019370 return 1;
19371 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019372 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019373 return 1;
19374 }
19375 }
19376 return 0;
19377}
19378
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019379sub specificHeader($$)
19380{
19381 my ($Header, $Spec) = @_;
19382 my $Name = get_filename($Header);
19383
19384 if($Spec eq "windows")
19385 {# MS Windows
19386 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19387 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19388 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19389 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19390 my @Dirs = (
19391 "win32",
19392 "win64",
19393 "win",
19394 "windows",
19395 "msvcrt"
19396 ); # /gsf-win32/
19397 if(my $DIRs = join("|", @Dirs)) {
19398 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19399 }
19400 }
19401 elsif($Spec eq "macos")
19402 { # Mac OS
19403 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19404 }
19405
19406 return 0;
19407}
19408
19409sub skipAlienHeader($)
19410{
19411 my $Path = $_[0];
19412 my $Name = get_filename($Path);
19413 my $Dir = get_dirname($Path);
19414
19415 if($Tolerance=~/2/)
19416 { # 2 - skip internal headers
19417 my @Terms = (
19418 "p",
19419 "priv",
19420 "int",
19421 "impl",
19422 "implementation",
19423 "internal",
19424 "private",
19425 "old",
19426 "compat",
19427 "debug",
19428 "test",
19429 "gen"
19430 );
19431
19432 my @Dirs = (
19433 "private",
19434 "priv",
19435 "port",
19436 "impl",
19437 "internal",
19438 "detail",
19439 "details",
19440 "old",
19441 "compat",
19442 "debug",
19443 "config",
19444 "compiler",
19445 "platform",
19446 "test"
19447 );
19448
19449 if(my $TERMs = join("|", @Terms)) {
19450 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19451 }
19452 if(my $DIRs = join("|", @Dirs)) {
19453 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19454 }
19455
19456 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19457 }
19458
19459 if($Tolerance=~/1/)
19460 { # 1 - skip non-Linux headers
19461 if($OSgroup ne "windows")
19462 {
19463 if(specificHeader($Path, "windows")) {
19464 return 1;
19465 }
19466 }
19467 if($OSgroup ne "macos")
19468 {
19469 if(specificHeader($Path, "macos")) {
19470 return 1;
19471 }
19472 }
19473 }
19474
19475 # valid
19476 return 0;
19477}
19478
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019479sub skipHeader($$)
19480{
19481 my ($Path, $LibVersion) = @_;
19482 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019483 if(defined $Cache{"skipHeader"}{$Path}) {
19484 return $Cache{"skipHeader"}{$Path};
19485 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019486 if(defined $Tolerance and $Tolerance=~/1|2/)
19487 { # --tolerant
19488 if(skipAlienHeader($Path)) {
19489 return ($Cache{"skipHeader"}{$Path} = 1);
19490 }
19491 }
19492 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19493 return 0;
19494 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019495 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19496}
19497
19498sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019499{ # returns:
19500 # 1 - if header should NOT be included and checked
19501 # 2 - if header should NOT be included, but should be checked
19502 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019503 my $Name = get_filename($Path);
19504 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019505 return $Kind;
19506 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019507 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19508 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019509 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019510 if(index($Path, $D)!=-1)
19511 {
19512 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19513 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019515 }
19516 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019517 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19518 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019519 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019520 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19521 {
19522 if($Name=~/$P/) {
19523 return $Kind;
19524 }
19525 if($P=~/[\/\\]/ and $Path=~/$P/) {
19526 return $Kind;
19527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019528 }
19529 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019530
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019531 return 0;
19532}
19533
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019534sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019535{
19536 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019537 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019538 { # system directory
19539 return;
19540 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019541 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019542 { # already registered
19543 return;
19544 }
19545 foreach my $Path (find_libs($Dir,"",1))
19546 {
19547 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019548 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019549 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019550 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019551 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19552}
19553
19554sub registerObject($$)
19555{
19556 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019557
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019558 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019559 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019560 if($OSgroup=~/linux|bsd/i)
19561 {
19562 if(my $SONAME = getSONAME($Path)) {
19563 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19564 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019565 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019566 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19567 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019568 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019569
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019570 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019571 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019572 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019573 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019574 if($ObjArch ne getArch_GCC($LibVersion))
19575 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19576 $CheckedArch{$LibVersion} = 1;
19577 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 +040019578 }
19579 }
19580 }
19581}
19582
19583sub getArch_Object($)
19584{
19585 my $Path = $_[0];
19586
19587 my %MachineType = (
19588 "14C" => "x86",
19589 "8664" => "x86_64",
19590 "1C0" => "arm",
19591 "200" => "ia64"
19592 );
19593
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019594 my %ArchName = (
19595 "s390:31-bit" => "s390",
19596 "s390:64-bit" => "s390x",
19597 "powerpc:common" => "ppc32",
19598 "powerpc:common64" => "ppc64",
19599 "i386:x86-64" => "x86_64",
19600 "mips:3000" => "mips",
19601 "sparc:v8plus" => "sparcv9"
19602 );
19603
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019604 if($OSgroup eq "windows")
19605 {
19606 my $DumpbinCmd = get_CmdPath("dumpbin");
19607 if(not $DumpbinCmd) {
19608 exitStatus("Not_Found", "can't find \"dumpbin\"");
19609 }
19610
19611 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19612 my $Out = `$Cmd`;
19613
19614 if($Out=~/(\w+)\smachine/)
19615 {
19616 if(my $Type = $MachineType{uc($1)})
19617 {
19618 return $Type;
19619 }
19620 }
19621 }
19622 elsif($OSgroup=~/linux|bsd/)
19623 {
19624 my $ObjdumpCmd = get_CmdPath("objdump");
19625 if(not $ObjdumpCmd) {
19626 exitStatus("Not_Found", "can't find \"objdump\"");
19627 }
19628
19629 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
19630 my $Out = `$Cmd`;
19631
19632 if($Out=~/architecture:\s+([\w\-\:]+)/)
19633 {
19634 my $Arch = $1;
19635 if($Arch=~s/\:(.+)//)
19636 {
19637 my $Suffix = $1;
19638
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019639 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019640 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019641 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019642 }
19643 }
19644
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019645 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019646 $Arch = "x86";
19647 }
19648
19649 if($Arch eq "x86-64") {
19650 $Arch = "x86_64";
19651 }
19652
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019653 if($Arch eq "ia64-elf64") {
19654 $Arch = "ia64";
19655 }
19656
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019657 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019658 }
19659 }
19660 else
19661 { # macos, etc.
19662 # TODO
19663 }
19664
19665 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019666}
19667
19668sub getSONAME($)
19669{
19670 my $Path = $_[0];
19671 return if(not $Path);
19672 if(defined $Cache{"getSONAME"}{$Path}) {
19673 return $Cache{"getSONAME"}{$Path};
19674 }
19675 my $ObjdumpCmd = get_CmdPath("objdump");
19676 if(not $ObjdumpCmd) {
19677 exitStatus("Not_Found", "can't find \"objdump\"");
19678 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019679 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019680 if($OSgroup eq "windows") {
19681 $SonameCmd .= " | find \"SONAME\"";
19682 }
19683 else {
19684 $SonameCmd .= " | grep SONAME";
19685 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019686 if(my $SonameInfo = `$SonameCmd`)
19687 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019688 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19689 return ($Cache{"getSONAME"}{$Path} = $1);
19690 }
19691 }
19692 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019693}
19694
19695sub getSOPaths_Dest($$)
19696{
19697 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019698 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019699 return ();
19700 }
19701 if(-f $Dest)
19702 {
19703 if(not parse_libname($Dest, "name", $OStarget)) {
19704 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19705 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019706 registerObject($Dest, $LibVersion);
19707 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019708 return ($Dest);
19709 }
19710 elsif(-d $Dest)
19711 {
19712 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019713 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019714 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019715 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19716 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019717 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019718 { # all files and symlinks that match the name of a library
19719 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19720 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019721 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019722 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019723 }
19724 }
19725 }
19726 else
19727 { # search for all files and symlinks
19728 foreach my $Path (find_libs($Dest,"",""))
19729 {
19730 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019731 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019732 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019733 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019734 }
19735 if($OSgroup eq "macos")
19736 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019737 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019738 {
19739 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019740 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019741 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019742 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19743 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019744 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019745 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019746 }
19747 }
19748 }
19749 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019750 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019751 }
19752 else {
19753 return ();
19754 }
19755}
19756
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019757sub isCyclical($$)
19758{
19759 my ($Stack, $Value) = @_;
19760 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019761}
19762
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019763sub getGCC_Opts($)
19764{ # to use in module
19765 my $LibVersion = $_[0];
19766
19767 my @Opts = ();
19768
19769 if($CompilerOptions{$LibVersion})
19770 { # user-defined options
19771 push(@Opts, $CompilerOptions{$LibVersion});
19772 }
19773 if($GccOptions)
19774 { # additional
19775 push(@Opts, $GccOptions);
19776 }
19777
19778 if(@Opts) {
19779 return join(" ", @Opts);
19780 }
19781
19782 return undef;
19783}
19784
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019785sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019786{
19787 my $LibVersion = $_[0];
19788
19789 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19790 return $Cache{"getArch_GCC"}{$LibVersion};
19791 }
19792
19793 my $Arch = undef;
19794
19795 if($GCC_PATH)
19796 {
19797 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19798
19799 my $Cmd = $GCC_PATH." test.c -o test";
19800 if(my $Opts = getGCC_Opts($LibVersion))
19801 { # user-defined options
19802 $Cmd .= " ".$Opts;
19803 }
19804
19805 chdir($TMP_DIR);
19806 system($Cmd);
19807 chdir($ORIG_DIR);
19808
19809 $Arch = getArch_Object("$TMP_DIR/test");
19810
19811 unlink("$TMP_DIR/test.c");
19812 unlink("$TMP_DIR/test");
19813 }
19814
19815 if(not $Arch) {
19816 exitStatus("Error", "can't check ARCH type");
19817 }
19818
19819 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19820}
19821
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019822sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019823{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019824 my $LibVersion = $_[0];
19825
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019826 my $Size = undef;
19827
19828 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019829 if(my $Arch = getArch($LibVersion))
19830 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019831 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019832 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019833 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019834 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19835 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019836 }
19837 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019838
19839 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019840 {
19841 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019842
19843 my $Cmd = $GCC_PATH." -E -dD empty.h";
19844 if(my $Opts = getGCC_Opts($LibVersion))
19845 { # user-defined options
19846 $Cmd .= " ".$Opts;
19847 }
19848
19849 chdir($TMP_DIR);
19850 my $Defines = `$Cmd`;
19851 chdir($ORIG_DIR);
19852
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019853 unlink("$TMP_DIR/empty.h");
19854
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019855 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19856 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019857 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019858 }
19859 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19860 { # GCC 3
19861 my $PTRDIFF = $1;
19862 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019863 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019864 }
19865 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019866 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019867 }
19868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019869 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019870
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019871 if(not $Size) {
19872 exitStatus("Error", "can't check WORD size");
19873 }
19874
19875 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019876}
19877
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019878sub getWordSize($)
19879{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019880 return $WORD_SIZE{$_[0]};
19881}
19882
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019883sub majorVersion($)
19884{
19885 my $V = $_[0];
19886 return 0 if(not $V);
19887 my @VParts = split(/\./, $V);
19888 return $VParts[0];
19889}
19890
19891sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019892{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019893 my ($V1, $V2) = @_;
19894 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019895 my @V1Parts = split(/\./, $V1);
19896 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019897 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19898 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019899 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19900 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19901 }
19902 return -1 if($#V1Parts < $#V2Parts);
19903 return 1 if($#V1Parts > $#V2Parts);
19904 return 0;
19905}
19906
19907sub read_ABI_Dump($$)
19908{
19909 my ($LibVersion, $Path) = @_;
19910 return if(not $LibVersion or not -e $Path);
19911 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019912 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019913 { # input *.abi
19914 $FilePath = $Path;
19915 }
19916 else
19917 { # input *.abi.tar.gz
19918 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019919 if(not isDump_U($FilePath)) {
19920 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019922 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019923
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019924 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019925
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019926 my $Line = readLineNum($FilePath, 0);
19927 if($Line=~/xml/)
19928 { # XML format
19929 loadModule("XmlDump");
19930 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019931 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019932 else
19933 { # Perl Data::Dumper format (default)
19934 open(DUMP, $FilePath);
19935 local $/ = undef;
19936 my $Content = <DUMP>;
19937 close(DUMP);
19938
19939 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19940 { # remove temp file
19941 unlink($FilePath);
19942 }
19943 if($Content!~/};\s*\Z/) {
19944 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19945 }
19946 $ABI = eval($Content);
19947 if(not $ABI) {
19948 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019950 }
19951 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019952 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019953 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019954 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019955 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019956 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019957 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019958 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019959 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019960
19961 if($ABI->{"ABI_DUMP_VERSION"})
19962 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019963 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019964 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019965 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019966 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019967 }
19968 else
19969 { # support for old ABI dumps
19970 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019971 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019972 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019973 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019974 }
19975 if(majorVersion($DVersion)<2)
19976 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019977 if($UseOldDumps)
19978 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019979 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19980 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019981 }
19982 }
19983 else
19984 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019985 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019986 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019987 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019988 }
19989 exitStatus("Dump_Version", $Msg);
19990 }
19991 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019992
19993 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19994 { # DWARF ABI Dump
19995 $UseConv_Real{$LibVersion}{"P"} = 1;
19996 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19997
19998 $UsedDump{$LibVersion}{"DWARF"} = 1;
19999
20000 $TargetComponent = "module";
20001 }
20002
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020003 if(not checkDump($LibVersion, "2.11"))
20004 { # old ABI dumps
20005 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020006 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020007 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020008 { # ABI dump created with --binary option
20009 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20010 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020011 else
20012 { # default
20013 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20014 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020015
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020016 if(defined $ABI->{"Mode"}
20017 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020018 { # --ext option
20019 $ExtendedCheck = 1;
20020 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020021 if($ABI->{"Extra"}) {
20022 $ExtraDump = 1;
20023 }
20024
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020025 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020026 {
20027 $UsedDump{$LibVersion}{"L"} = $Lang;
20028 setLanguage($LibVersion, $Lang);
20029 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020030 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020031 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020032 }
20033 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020034 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020035 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020036 if(not $TInfo)
20037 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020038 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020039 }
20040 my %Tid_TDid = ();
20041 foreach my $TDid (keys(%{$TInfo}))
20042 {
20043 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20044 {
20045 $MAX_ID = $Tid if($Tid>$MAX_ID);
20046 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020047 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020048 }
20049 }
20050 my %NewID = ();
20051 foreach my $Tid (keys(%Tid_TDid))
20052 {
20053 my @TDids = keys(%{$Tid_TDid{$Tid}});
20054 if($#TDids>=1)
20055 {
20056 foreach my $TDid (@TDids)
20057 {
20058 if($TDid) {
20059 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20060 }
20061 else
20062 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020063 my $ID = ++$MAX_ID;
20064
20065 $NewID{$TDid}{$Tid} = $ID;
20066 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20067 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020068 }
20069 }
20070 }
20071 else
20072 {
20073 my $TDid = $TDids[0];
20074 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20075 }
20076 }
20077 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20078 {
20079 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20080 if(defined $Info{"BaseType"})
20081 {
20082 my $Bid = $Info{"BaseType"}{"Tid"};
20083 my $BDid = $Info{"BaseType"}{"TDid"};
20084 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020085 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020086 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20087 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020089 }
20090 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020092 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020093 read_Machine_DumpInfo($ABI, $LibVersion);
20094 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020095 if(not $SymbolInfo{$LibVersion})
20096 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020097 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020098 }
20099 if(not keys(%{$SymbolInfo{$LibVersion}}))
20100 { # validation of old-version dumps
20101 if(not $ExtendedCheck) {
20102 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20103 }
20104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020105 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020106 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020107 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020108 else
20109 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020110 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020111 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020112 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020113 }
20114 if(not $DepSymbols)
20115 { # Cannot reconstruct DepSymbols. This may result in false
20116 # positives if the old dump is for library 2. Not a problem if
20117 # old dumps are only from old libraries.
20118 $DepSymbols = {};
20119 }
20120 foreach my $Symbol (keys(%{$DepSymbols})) {
20121 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020123 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020124 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020125
20126 if(my $V = $TargetVersion{$LibVersion}) {
20127 $Descriptor{$LibVersion}{"Version"} = $V;
20128 }
20129 else {
20130 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20131 }
20132
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020133 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020134 if(not $SkipTypes{$LibVersion})
20135 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020136 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020137 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020138 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020139 if(not $SkipSymbols{$LibVersion})
20140 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020141 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020142 }
20143 if(not $SkipSymbols{$LibVersion})
20144 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020145 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020146 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020147 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
20148 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20149 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020150 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020151 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020152 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020153 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020154 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020155 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020156 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020157 if(not checkDump($LibVersion, "2.10.1")
20158 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020159 { # support for old ABI dumps: added target headers
20160 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020161 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020162 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020163 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020164 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020166 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020167 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020168 if(defined $ABI->{"GccConstants"})
20169 { # 3.0
20170 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20171 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20172 }
20173 }
20174
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020175 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020176 if(not $NestedNameSpaces{$LibVersion})
20177 { # support for old dumps
20178 # Cannot reconstruct NameSpaces. This may affect design
20179 # of the compatibility report.
20180 $NestedNameSpaces{$LibVersion} = {};
20181 }
20182 # target system type
20183 # needed to adopt HTML report
20184 if(not $DumpSystem)
20185 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020186 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020187 }
20188 # recreate environment
20189 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20190 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020191 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020192 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020193 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20194 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020195 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020196 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020197 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020198 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20199 {
20200 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20201 setLanguage($LibVersion, "C++");
20202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020203 }
20204 }
20205 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020206 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20207 {
20208 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20209 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20210 }
20211 }
20212
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020213 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020214 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020215 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020216 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020217 {
20218 if(not $Symbol_Library{$LibVersion}{$MnglName}
20219 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20220 push(@VFunc, $MnglName);
20221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020222 }
20223 }
20224 translateSymbols(@VFunc, $LibVersion);
20225 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020226 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20227
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020228 if(not checkDump($LibVersion, "3.0"))
20229 { # support for old ABI dumps
20230 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20231 {
20232 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20233 {
20234 if(ref($BaseType) eq "HASH") {
20235 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20236 }
20237 }
20238 }
20239 }
20240
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020241 if(not checkDump($LibVersion, "3.2"))
20242 { # support for old ABI dumps
20243 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20244 {
20245 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20246 {
20247 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20248 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20249 }
20250 }
20251 }
20252
20253 # repair target headers list
20254 delete($TargetHeaders{$LibVersion});
20255 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020256 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20257 }
20258 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20259 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020260 }
20261
20262 # non-target constants from anon enums
20263 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20264 {
20265 if(not $ExtraDump
20266 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20267 {
20268 delete($Constants{$LibVersion}{$Name});
20269 }
20270 }
20271 }
20272
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020273 if(not checkDump($LibVersion, "2.20"))
20274 { # support for old ABI dumps
20275 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20276 {
20277 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20278
20279 if($TType=~/Struct|Union|Enum|Typedef/)
20280 { # repair complex types first
20281 next;
20282 }
20283
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020284 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020285 {
20286 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20287 if($BType=~/Struct|Union|Enum/i)
20288 {
20289 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20290 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20291 }
20292 }
20293 }
20294 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20295 {
20296 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20297 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20298 if($TType=~/Struct|Union|Enum/) {
20299 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20300 }
20301 }
20302 }
20303
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020304 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020305 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020306 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20307 { # support for old ABI dumps < 2.0 (ACC 1.22)
20308 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20309 {
20310 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20311 {
20312 if($Access ne "public") {
20313 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20314 }
20315 }
20316 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20317 }
20318 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20319 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020320 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20321 { # support for old ABI dumps
20322 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20323 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020324 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20325 { # DWARF ABI Dumps
20326 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20327 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020328 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20329 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20330 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020331 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20332 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020333 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020334 foreach (keys(%{$TInfo{"Base"}})) {
20335 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020336 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020337 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020338 if($TInfo{"Type"} eq "MethodPtr")
20339 {
20340 if(defined $TInfo{"Param"})
20341 { # support for old ABI dumps <= 1.17
20342 if(not defined $TInfo{"Param"}{"0"})
20343 {
20344 my $Max = keys(%{$TInfo{"Param"}});
20345 foreach my $Pos (1 .. $Max) {
20346 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20347 }
20348 delete($TInfo{"Param"}{$Max});
20349 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20350 }
20351 }
20352 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020353 if($TInfo{"BaseType"} eq $TypeId)
20354 { # fix ABI dump
20355 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20356 }
20357 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020358 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020359 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020360 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020361 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20362 if(not $BName)
20363 { # broken type
20364 next;
20365 }
20366 if($TInfo{"Name"} eq $BName)
20367 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020368 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020369 next;
20370 }
20371 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20372 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020373 }
20374 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020375 }
20376 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20377 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020378 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020379 }
20380 }
20381
20382 if(not checkDump($LibVersion, "2.15"))
20383 { # support for old ABI dumps
20384 my %Dups = ();
20385 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20386 {
20387 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020388 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020389 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20390 { # remove template decls
20391 delete($SymbolInfo{$LibVersion}{$InfoId});
20392 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020393 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020394 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020395 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20396 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020397 { # templates
20398 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020399 }
20400 }
20401 }
20402
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020403 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20404 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020405 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20406 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20407 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20408 { # support for old ABI dumps (< 3.1)
20409 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20410 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20411 { # add "this" first parameter
20412 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20413 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20414
20415 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20416 {
20417 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20418 foreach my $Pos (reverse(0 .. $#Pos)) {
20419 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20420 }
20421 }
20422 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20423 }
20424 }
20425
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020426 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20427 { # ABI dumps have no mangled names for C-functions
20428 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020430 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20431 { # support for old ABI dumps
20432 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20433 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020434 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20435 { # DWARF ABI Dumps
20436 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20437 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020438 }
20439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020440 $Descriptor{$LibVersion}{"Dump"} = 1;
20441}
20442
20443sub read_Machine_DumpInfo($$)
20444{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020445 my ($ABI, $LibVersion) = @_;
20446 if($ABI->{"Arch"}) {
20447 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020448 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020449 if($ABI->{"WordSize"}) {
20450 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020451 }
20452 else
20453 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020454 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020455 }
20456 if(not $WORD_SIZE{$LibVersion})
20457 { # support for old dumps (<1.23)
20458 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20459 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020460 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461 }
20462 else
20463 {
20464 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020465 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020466 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020467 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20468 { # any "pointer"-type
20469 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020470 last;
20471 }
20472 }
20473 if($PSize)
20474 { # a pointer type size
20475 $WORD_SIZE{$LibVersion} = $PSize;
20476 }
20477 else {
20478 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20479 }
20480 }
20481 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020482 if($ABI->{"GccVersion"}) {
20483 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020484 }
20485}
20486
20487sub read_Libs_DumpInfo($$)
20488{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020489 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020490 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20491 if(not $Library_Symbol{$LibVersion})
20492 { # support for old dumps
20493 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020495 if(keys(%{$Library_Symbol{$LibVersion}})
20496 and not $DumpAPI) {
20497 $Descriptor{$LibVersion}{"Libs"} = "OK";
20498 }
20499}
20500
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020501sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020502{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020503 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020504
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020505 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020506 and not $DumpAPI) {
20507 $Descriptor{$LibVersion}{"Headers"} = "OK";
20508 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020509 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020510 { # headers info is stored in the old dumps in the different way
20511 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020512 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020513 { # support for old dumps: headers info corrected in 1.22
20514 $Identity = $Name;
20515 }
20516 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020517 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020518 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020519
20520 if(keys(%{$ABI->{"Sources"}})
20521 and not $DumpAPI) {
20522 $Descriptor{$LibVersion}{"Sources"} = "OK";
20523 }
20524 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20525 { # headers info is stored in the old dumps in the different way
20526 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20527 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020529}
20530
20531sub find_libs($$$)
20532{
20533 my ($Path, $Type, $MaxDepth) = @_;
20534 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020535 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020536}
20537
20538sub createDescriptor($$)
20539{
20540 my ($LibVersion, $Path) = @_;
20541 if(not $LibVersion or not $Path
20542 or not -e $Path) {
20543 return "";
20544 }
20545 if(-d $Path)
20546 { # directory with headers files and shared objects
20547 return "
20548 <version>
20549 ".$TargetVersion{$LibVersion}."
20550 </version>
20551
20552 <headers>
20553 $Path
20554 </headers>
20555
20556 <libs>
20557 $Path
20558 </libs>";
20559 }
20560 else
20561 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020562 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020563 { # standard XML-descriptor
20564 return readFile($Path);
20565 }
20566 elsif(is_header($Path, 2, $LibVersion))
20567 { # header file
20568 return "
20569 <version>
20570 ".$TargetVersion{$LibVersion}."
20571 </version>
20572
20573 <headers>
20574 $Path
20575 </headers>
20576
20577 <libs>
20578 none
20579 </libs>";
20580 }
20581 elsif(parse_libname($Path, "name", $OStarget))
20582 { # shared object
20583 return "
20584 <version>
20585 ".$TargetVersion{$LibVersion}."
20586 </version>
20587
20588 <headers>
20589 none
20590 </headers>
20591
20592 <libs>
20593 $Path
20594 </libs>";
20595 }
20596 else
20597 { # standard XML-descriptor
20598 return readFile($Path);
20599 }
20600 }
20601}
20602
20603sub detect_lib_default_paths()
20604{
20605 my %LPaths = ();
20606 if($OSgroup eq "bsd")
20607 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020608 if(my $LdConfig = get_CmdPath("ldconfig"))
20609 {
20610 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20611 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020612 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20613 {
20614 my $Name = "lib".$1;
20615 if(not defined $LPaths{$Name}) {
20616 $LPaths{$Name} = $2;
20617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020618 }
20619 }
20620 }
20621 else {
20622 printMsg("WARNING", "can't find ldconfig");
20623 }
20624 }
20625 else
20626 {
20627 if(my $LdConfig = get_CmdPath("ldconfig"))
20628 {
20629 if($SystemRoot and $OSgroup eq "linux")
20630 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20631 if(-e $SystemRoot."/etc/ld.so.conf") {
20632 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20633 }
20634 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020635 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20636 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020637 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20638 {
20639 my ($Name, $Path) = ($1, $2);
20640 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020641 if(not defined $LPaths{$Name})
20642 { # get first element from the list of available paths
20643
20644 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20645 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20646 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20647
20648 $LPaths{$Name} = $Path;
20649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020650 }
20651 }
20652 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020653 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020654 printMsg("WARNING", "can't find ldconfig");
20655 }
20656 }
20657 return \%LPaths;
20658}
20659
20660sub detect_bin_default_paths()
20661{
20662 my $EnvPaths = $ENV{"PATH"};
20663 if($OSgroup eq "beos") {
20664 $EnvPaths.=":".$ENV{"BETOOLS"};
20665 }
20666 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020667 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020668 {
20669 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020670 next if(not $Path);
20671 if($SystemRoot
20672 and $Path=~/\A\Q$SystemRoot\E\//)
20673 { # do NOT use binaries from target system
20674 next;
20675 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020676 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020677 }
20678}
20679
20680sub detect_inc_default_paths()
20681{
20682 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020683 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020684 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020685 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020686 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020687 next if(index($Line, "/cc1plus ")!=-1);
20688
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020689 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20690 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020691 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020692 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020693 if(index($Path, "c++")!=-1
20694 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020695 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020696 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020697 if(not defined $MAIN_CPP_DIR
20698 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20699 $MAIN_CPP_DIR = $Path;
20700 }
20701 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020702 elsif(index($Path, "gcc")!=-1) {
20703 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020704 }
20705 else
20706 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020707 if($Path=~/local[\/\\]+include/)
20708 { # local paths
20709 next;
20710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 if($SystemRoot
20712 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20713 { # The GCC include path for user headers is not a part of the system root
20714 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20715 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20716 next;
20717 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020718 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020719 }
20720 }
20721 }
20722 unlink("$TMP_DIR/empty.h");
20723 return %DPaths;
20724}
20725
20726sub detect_default_paths($)
20727{
20728 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20729 my $Search = $_[0];
20730 if($Search!~/inc/) {
20731 $HSearch = 0;
20732 }
20733 if($Search!~/lib/) {
20734 $LSearch = 0;
20735 }
20736 if($Search!~/bin/) {
20737 $BSearch = 0;
20738 }
20739 if($Search!~/gcc/) {
20740 $GSearch = 0;
20741 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020742 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020743 { # <search_headers> section of the XML descriptor
20744 # do NOT search for systems headers
20745 $HSearch = 0;
20746 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020747 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020748 { # <search_headers> section of the XML descriptor
20749 # do NOT search for systems headers
20750 $LSearch = 0;
20751 }
20752 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20753 { # additional search paths
20754 next if($Type eq "include" and not $HSearch);
20755 next if($Type eq "lib" and not $LSearch);
20756 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020757 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 }
20759 if($OSgroup ne "windows")
20760 { # unix-like
20761 foreach my $Type ("include", "lib", "bin")
20762 { # automatic detection of system "devel" directories
20763 next if($Type eq "include" and not $HSearch);
20764 next if($Type eq "lib" and not $LSearch);
20765 next if($Type eq "bin" and not $BSearch);
20766 my ($UsrDir, $RootDir) = ("/usr", "/");
20767 if($SystemRoot and $Type ne "bin")
20768 { # 1. search for target headers and libraries
20769 # 2. use host commands: ldconfig, readelf, etc.
20770 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20771 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020772 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020773 if(-d $RootDir."/".$Type)
20774 { # if "/lib" is symbolic link
20775 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020776 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020777 }
20778 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020779 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020780 }
20781 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020782 if(-d $UsrDir)
20783 {
20784 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 if(-d $UsrDir."/".$Type)
20786 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020787 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020788 }
20789 }
20790 }
20791 }
20792 if($BSearch)
20793 {
20794 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020795 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020796 }
20797 # check environment variables
20798 if($OSgroup eq "beos")
20799 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020800 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020801 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020802 if($_ eq ".") {
20803 next;
20804 }
20805 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20806 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20807 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020808 }
20809 }
20810 if($HSearch)
20811 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020812 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20813 split(/:|;/, $ENV{"BEINCLUDES"})
20814 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020815 }
20816 if($LSearch)
20817 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020818 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20819 split(/:|;/, $ENV{"BELIBRARIES"}),
20820 split(/:|;/, $ENV{"LIBRARY_PATH"})
20821 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020822 }
20823 }
20824 if($LSearch)
20825 { # using linker to get system paths
20826 if(my $LPaths = detect_lib_default_paths())
20827 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020828 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020829 foreach my $Name (keys(%{$LPaths}))
20830 {
20831 if($SystemRoot
20832 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20833 { # wrong ldconfig configuration
20834 # check your <sysroot>/etc/ld.so.conf
20835 next;
20836 }
20837 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020838 if(my $Dir = get_dirname($LPaths->{$Name})) {
20839 $Dirs{$Dir} = 1;
20840 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020841 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020842 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020843 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020844 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020845 }
20846 if($BSearch)
20847 {
20848 if($CrossGcc)
20849 { # --cross-gcc=arm-linux-gcc
20850 if(-e $CrossGcc)
20851 { # absolute or relative path
20852 $GCC_PATH = get_abs_path($CrossGcc);
20853 }
20854 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20855 { # command name
20856 $GCC_PATH = $CrossGcc;
20857 }
20858 else {
20859 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20860 }
20861 if($GCC_PATH=~/\s/) {
20862 $GCC_PATH = "\"".$GCC_PATH."\"";
20863 }
20864 }
20865 }
20866 if($GSearch)
20867 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020868 if(not $CrossGcc)
20869 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020870 $GCC_PATH = get_CmdPath("gcc");
20871 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020872 if(not $GCC_PATH)
20873 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020874 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020875 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020876 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020877 { # select the latest version
20878 @GCCs = sort {$b cmp $a} @GCCs;
20879 if(check_gcc($GCCs[0], "3"))
20880 {
20881 $GCC_PATH = $GCCs[0];
20882 last;
20883 }
20884 }
20885 }
20886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020887 if(not $GCC_PATH) {
20888 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20889 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020890
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020891 if(not $CheckObjectsOnly_Opt)
20892 {
20893 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20894 {
20895 my $GccTarget = get_dumpmachine($GCC_PATH);
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020896 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020897 if($GccTarget=~/symbian/)
20898 {
20899 $OStarget = "symbian";
20900 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20901 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020902
20903 # check GCC version
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020904 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020905 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040020906 # introduced in 4.8
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020907 # fixed in 4.8.3
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020908 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20909 $EMERGENCY_MODE_48 = 1;
20910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020911 }
20912 else {
20913 exitStatus("Error", "something is going wrong with the GCC compiler");
20914 }
20915 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020916 if($HSearch)
20917 {
20918 if(not $NoStdInc)
20919 { # do NOT search in GCC standard paths
20920 my %DPaths = detect_inc_default_paths();
20921 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20922 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20923 @DefaultIncPaths = @{$DPaths{"Inc"}};
20924 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020925 }
20926 }
20927 }
20928 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020929 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020930 my $IncPath = "/usr/include";
20931 if($SystemRoot) {
20932 $IncPath = $SystemRoot.$IncPath;
20933 }
20934 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020935 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020936 }
20937 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020938
20939 if($ExtraInfo)
20940 {
20941 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20942 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020944}
20945
20946sub getLIB_EXT($)
20947{
20948 my $Target = $_[0];
20949 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20950 return $Ext;
20951 }
20952 return $OS_LibExt{$LIB_TYPE}{"default"};
20953}
20954
20955sub getAR_EXT($)
20956{
20957 my $Target = $_[0];
20958 if(my $Ext = $OS_Archive{$Target}) {
20959 return $Ext;
20960 }
20961 return $OS_Archive{"default"};
20962}
20963
20964sub get_dumpversion($)
20965{
20966 my $Cmd = $_[0];
20967 return "" if(not $Cmd);
20968 if($Cache{"get_dumpversion"}{$Cmd}) {
20969 return $Cache{"get_dumpversion"}{$Cmd};
20970 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020971 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020972 chomp($V);
20973 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20974}
20975
20976sub get_dumpmachine($)
20977{
20978 my $Cmd = $_[0];
20979 return "" if(not $Cmd);
20980 if($Cache{"get_dumpmachine"}{$Cmd}) {
20981 return $Cache{"get_dumpmachine"}{$Cmd};
20982 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020983 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020984 chomp($Machine);
20985 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20986}
20987
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020988sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020989{
20990 my $Cmd = $_[0];
20991 return "" if(not $Cmd);
20992 my @Options = (
20993 "--version",
20994 "-help"
20995 );
20996 foreach my $Opt (@Options)
20997 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020998 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020999 if($Info) {
21000 return 1;
21001 }
21002 }
21003 return 0;
21004}
21005
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021006sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021007{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021008 my ($Cmd, $ReqVer) = @_;
21009 return 0 if(not $Cmd or not $ReqVer);
21010 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21011 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021012 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021013 if(my $GccVer = get_dumpversion($Cmd))
21014 {
21015 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21016 if(cmpVersions($GccVer, $ReqVer)>=0) {
21017 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21018 }
21019 }
21020 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021021}
21022
21023sub get_depth($)
21024{
21025 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021026 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021027 }
21028 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21029}
21030
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021031sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021032{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021033 return if($Cache{"registerGccHeaders"}); # this function should be called once
21034
21035 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021036 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021037 my @Headers = cmd_find($Path,"f");
21038 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21039 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021040 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 my $FileName = get_filename($HPath);
21042 if(not defined $DefaultGccHeader{$FileName})
21043 { # skip duplicated
21044 $DefaultGccHeader{$FileName} = $HPath;
21045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021046 }
21047 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021048 $Cache{"registerGccHeaders"} = 1;
21049}
21050
21051sub registerCppHeaders()
21052{
21053 return if($Cache{"registerCppHeaders"}); # this function should be called once
21054
21055 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021056 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021057 my @Headers = cmd_find($CppDir,"f");
21058 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21059 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021060 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021061 my $FileName = get_filename($Path);
21062 if(not defined $DefaultCppHeader{$FileName})
21063 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021064 $DefaultCppHeader{$FileName} = $Path;
21065 }
21066 }
21067 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021068 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021069}
21070
21071sub parse_libname($$$)
21072{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021073 return "" if(not $_[0]);
21074 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21075 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021076 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021077 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21078}
21079
21080sub parse_libname_I($$$)
21081{
21082 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021083
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021084 if($Target eq "symbian") {
21085 return parse_libname_symbian($Name, $Type);
21086 }
21087 elsif($Target eq "windows") {
21088 return parse_libname_windows($Name, $Type);
21089 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021090
21091 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021092 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021093 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021094 { # libSDL-1.2.so.0.7.1
21095 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021096 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021097 if($Type eq "name")
21098 { # libSDL-1.2
21099 # libwbxml2
21100 return $2;
21101 }
21102 elsif($Type eq "name+ext")
21103 { # libSDL-1.2.so
21104 # libwbxml2.so
21105 return $1;
21106 }
21107 elsif($Type eq "version")
21108 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021109 if(defined $7
21110 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021111 { # 0.7.1
21112 return $7;
21113 }
21114 else
21115 { # libc-2.5.so (=>2.5 version)
21116 my $MV = $5;
21117 $MV=~s/\A[\-\_]+//g;
21118 return $MV;
21119 }
21120 }
21121 elsif($Type eq "short")
21122 { # libSDL
21123 # libwbxml2
21124 return $3;
21125 }
21126 elsif($Type eq "shortest")
21127 { # SDL
21128 # wbxml
21129 return shortest_name($3);
21130 }
21131 }
21132 return "";# error
21133}
21134
21135sub parse_libname_symbian($$)
21136{
21137 my ($Name, $Type) = @_;
21138 my $Ext = getLIB_EXT("symbian");
21139 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21140 { # libpthread{00010001}.dso
21141 if($Type eq "name")
21142 { # libpthread{00010001}
21143 return $2;
21144 }
21145 elsif($Type eq "name+ext")
21146 { # libpthread{00010001}.dso
21147 return $1;
21148 }
21149 elsif($Type eq "version")
21150 { # 00010001
21151 my $V = $4;
21152 $V=~s/\{(.+)\}/$1/;
21153 return $V;
21154 }
21155 elsif($Type eq "short")
21156 { # libpthread
21157 return $3;
21158 }
21159 elsif($Type eq "shortest")
21160 { # pthread
21161 return shortest_name($3);
21162 }
21163 }
21164 return "";# error
21165}
21166
21167sub parse_libname_windows($$)
21168{
21169 my ($Name, $Type) = @_;
21170 my $Ext = getLIB_EXT("windows");
21171 if($Name=~/((.+?)\.$Ext)\Z/)
21172 { # netapi32.dll
21173 if($Type eq "name")
21174 { # netapi32
21175 return $2;
21176 }
21177 elsif($Type eq "name+ext")
21178 { # netapi32.dll
21179 return $1;
21180 }
21181 elsif($Type eq "version")
21182 { # DLL version embedded
21183 # at binary-level
21184 return "";
21185 }
21186 elsif($Type eq "short")
21187 { # netapi32
21188 return $2;
21189 }
21190 elsif($Type eq "shortest")
21191 { # netapi
21192 return shortest_name($2);
21193 }
21194 }
21195 return "";# error
21196}
21197
21198sub shortest_name($)
21199{
21200 my $Name = $_[0];
21201 # remove prefix
21202 $Name=~s/\A(lib|open)//;
21203 # remove suffix
21204 $Name=~s/[\W\d_]+\Z//i;
21205 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21206 return $Name;
21207}
21208
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021209sub createSymbolsList($$$$$)
21210{
21211 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21212 read_ABI_Dump(1, $DPath);
21213 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021214 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021215 }
21216 my %SymbolHeaderLib = ();
21217 my $Total = 0;
21218 # Get List
21219 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21220 {
21221 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021222 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021223 next;
21224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021225 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021226 { # skip other symbols
21227 next;
21228 }
21229 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21230 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021231 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021232 next;
21233 }
21234 my $DyLib = $Symbol_Library{1}{$Symbol};
21235 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021236 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021237 next;
21238 }
21239 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21240 $Total+=1;
21241 }
21242 # Draw List
21243 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21244 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21245 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21246 {
21247 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21248 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021249 my %NS_Symbol = ();
21250 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021251 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021252 }
21253 foreach my $NameSpace (sort keys(%NS_Symbol))
21254 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021255 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021256 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21257 foreach my $Symbol (@SortedInterfaces)
21258 {
21259 my $SubReport = "";
21260 my $Signature = get_Signature($Symbol, 1);
21261 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021262 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263 }
21264 if($Symbol=~/\A(_Z|\?)/)
21265 {
21266 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021267 $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 +040021268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021269 else {
21270 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21271 }
21272 }
21273 else
21274 {
21275 if($Signature) {
21276 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21277 }
21278 else {
21279 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21280 }
21281 }
21282 $SYMBOLS_LIST .= $SubReport;
21283 }
21284 }
21285 $SYMBOLS_LIST .= "<br/>\n";
21286 }
21287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021288 # clear info
21289 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21290 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21291 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21292 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021293 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021294 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021295 my $CssStyles = readModule("Styles", "SymbolsList.css");
21296 my $JScripts = readModule("Scripts", "Sections.js");
21297 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021298 my $Title = "$LName: public symbols";
21299 my $Keywords = "$LName, API, symbols";
21300 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021301 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021302 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021303 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021304 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021305 writeFile($SaveTo, $SYMBOLS_LIST);
21306}
21307
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021308sub add_target_libs($)
21309{
21310 foreach (@{$_[0]}) {
21311 $TargetLibs{$_} = 1;
21312 }
21313}
21314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021315sub is_target_lib($)
21316{
21317 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021318 if(not $LName) {
21319 return 0;
21320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021321 if($TargetLibraryName
21322 and $LName!~/\Q$TargetLibraryName\E/) {
21323 return 0;
21324 }
21325 if(keys(%TargetLibs)
21326 and not $TargetLibs{$LName}
21327 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21328 return 0;
21329 }
21330 return 1;
21331}
21332
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021333sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021334{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021335 my ($H, $V) = @_;
21336 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021337 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021338 if($TargetHeaders{$V}{$H}) {
21339 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021340 }
21341 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021342 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021343}
21344
21345sub checkVersionNum($$)
21346{
21347 my ($LibVersion, $Path) = @_;
21348 if(my $VerNum = $TargetVersion{$LibVersion}) {
21349 return $VerNum;
21350 }
21351 my $UsedAltDescr = 0;
21352 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021353 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021354 next if(isDump($Part)); # ABI dump
21355 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021356 my $VerNum = "";
21357 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021358 {
21359 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021360 $VerNum = parse_libname($Part, "version", $OStarget);
21361 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021362 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021363 }
21364 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021365 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21366 {
21367 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021368 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021369 }
21370 if($VerNum ne "")
21371 {
21372 $TargetVersion{$LibVersion} = $VerNum;
21373 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021374 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021375 }
21376 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021377 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 +040021378 }
21379 return $TargetVersion{$LibVersion};
21380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021381 }
21382 if($UsedAltDescr)
21383 {
21384 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021385 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021386 }
21387 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021388 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021389 }
21390 }
21391}
21392
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021393sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021394{
21395 my $Str = $_[0];
21396 return "" if(not $Str);
21397 $Str=~s/\Q$TargetLibraryName\E//g;
21398 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021399 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021400 return $2;
21401 }
21402 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21403 return $V;
21404 }
21405 return "";
21406}
21407
21408sub readLibs($)
21409{
21410 my $LibVersion = $_[0];
21411 if($OStarget eq "windows")
21412 { # dumpbin.exe will crash
21413 # without VS Environment
21414 check_win32_env();
21415 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021416 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021417 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021418 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021419}
21420
21421sub dump_sorting($)
21422{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021423 my $Hash = $_[0];
21424 return [] if(not $Hash);
21425 my @Keys = keys(%{$Hash});
21426 return [] if($#Keys<0);
21427 if($Keys[0]=~/\A\d+\Z/)
21428 { # numbers
21429 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021430 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021431 else
21432 { # strings
21433 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021434 }
21435}
21436
21437sub printMsg($$)
21438{
21439 my ($Type, $Msg) = @_;
21440 if($Type!~/\AINFO/) {
21441 $Msg = $Type.": ".$Msg;
21442 }
21443 if($Type!~/_C\Z/) {
21444 $Msg .= "\n";
21445 }
21446 if($Quiet)
21447 { # --quiet option
21448 appendFile($COMMON_LOG_PATH, $Msg);
21449 }
21450 else
21451 {
21452 if($Type eq "ERROR") {
21453 print STDERR $Msg;
21454 }
21455 else {
21456 print $Msg;
21457 }
21458 }
21459}
21460
21461sub exitStatus($$)
21462{
21463 my ($Code, $Msg) = @_;
21464 printMsg("ERROR", $Msg);
21465 exit($ERROR_CODE{$Code});
21466}
21467
21468sub exitReport()
21469{ # the tool has run without any errors
21470 printReport();
21471 if($COMPILE_ERRORS)
21472 { # errors in headers may add false positives/negatives
21473 exit($ERROR_CODE{"Compile_Error"});
21474 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021475 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21476 { # --binary
21477 exit($ERROR_CODE{"Incompatible"});
21478 }
21479 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21480 { # --source
21481 exit($ERROR_CODE{"Incompatible"});
21482 }
21483 elsif($RESULT{"Source"}{"Problems"}
21484 or $RESULT{"Binary"}{"Problems"})
21485 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021486 exit($ERROR_CODE{"Incompatible"});
21487 }
21488 else {
21489 exit($ERROR_CODE{"Compatible"});
21490 }
21491}
21492
21493sub readRules($)
21494{
21495 my $Kind = $_[0];
21496 if(not -f $RULES_PATH{$Kind}) {
21497 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21498 }
21499 my $Content = readFile($RULES_PATH{$Kind});
21500 while(my $Rule = parseTag(\$Content, "rule"))
21501 {
21502 my $RId = parseTag(\$Rule, "id");
21503 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21504 foreach my $Prop (@Properties) {
21505 if(my $Value = parseTag(\$Rule, lc($Prop)))
21506 {
21507 $Value=~s/\n[ ]*//;
21508 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21509 }
21510 }
21511 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21512 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21513 }
21514 else {
21515 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21516 }
21517 }
21518}
21519
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021520sub getReportPath($)
21521{
21522 my $Level = $_[0];
21523 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21524 if($Level eq "Binary")
21525 {
21526 if($BinaryReportPath)
21527 { # --bin-report-path
21528 return $BinaryReportPath;
21529 }
21530 elsif($OutputReportPath)
21531 { # --report-path
21532 return $OutputReportPath;
21533 }
21534 else
21535 { # default
21536 return $Dir."/abi_compat_report.$ReportFormat";
21537 }
21538 }
21539 elsif($Level eq "Source")
21540 {
21541 if($SourceReportPath)
21542 { # --src-report-path
21543 return $SourceReportPath;
21544 }
21545 elsif($OutputReportPath)
21546 { # --report-path
21547 return $OutputReportPath;
21548 }
21549 else
21550 { # default
21551 return $Dir."/src_compat_report.$ReportFormat";
21552 }
21553 }
21554 else
21555 {
21556 if($OutputReportPath)
21557 { # --report-path
21558 return $OutputReportPath;
21559 }
21560 else
21561 { # default
21562 return $Dir."/compat_report.$ReportFormat";
21563 }
21564 }
21565}
21566
21567sub printStatMsg($)
21568{
21569 my $Level = $_[0];
21570 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21571}
21572
21573sub listAffected($)
21574{
21575 my $Level = $_[0];
21576 my $List = "";
21577 foreach (keys(%{$TotalAffected{$Level}}))
21578 {
21579 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21580 { # skip "Low"-severity problems
21581 next;
21582 }
21583 $List .= "$_\n";
21584 }
21585 my $Dir = get_dirname(getReportPath($Level));
21586 if($Level eq "Binary") {
21587 writeFile($Dir."/abi_affected.txt", $List);
21588 }
21589 elsif($Level eq "Source") {
21590 writeFile($Dir."/src_affected.txt", $List);
21591 }
21592}
21593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021594sub printReport()
21595{
21596 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021597 createReport();
21598 if($JoinReport or $DoubleReport)
21599 {
21600 if($RESULT{"Binary"}{"Problems"}
21601 or $RESULT{"Source"}{"Problems"}) {
21602 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021603 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021604 else {
21605 printMsg("INFO", "result: COMPATIBLE");
21606 }
21607 printStatMsg("Binary");
21608 printStatMsg("Source");
21609 if($ListAffected)
21610 { # --list-affected
21611 listAffected("Binary");
21612 listAffected("Source");
21613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021614 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021615 elsif($BinaryOnly)
21616 {
21617 if($RESULT{"Binary"}{"Problems"}) {
21618 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21619 }
21620 else {
21621 printMsg("INFO", "result: COMPATIBLE");
21622 }
21623 printStatMsg("Binary");
21624 if($ListAffected)
21625 { # --list-affected
21626 listAffected("Binary");
21627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021628 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021629 elsif($SourceOnly)
21630 {
21631 if($RESULT{"Source"}{"Problems"}) {
21632 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21633 }
21634 else {
21635 printMsg("INFO", "result: COMPATIBLE");
21636 }
21637 printStatMsg("Source");
21638 if($ListAffected)
21639 { # --list-affected
21640 listAffected("Source");
21641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021642 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021643 if($StdOut)
21644 {
21645 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021646 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021647 printMsg("INFO", "compatibility report has been generated to stdout");
21648 }
21649 else
21650 { # default
21651 printMsg("INFO", "compatibility reports have been generated to stdout");
21652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021654 else
21655 {
21656 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021658 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21659 }
21660 elsif($DoubleReport)
21661 { # default
21662 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21663 }
21664 elsif($BinaryOnly)
21665 { # --binary
21666 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21667 }
21668 elsif($SourceOnly)
21669 { # --source
21670 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021672 }
21673}
21674
21675sub check_win32_env()
21676{
21677 if(not $ENV{"DevEnvDir"}
21678 or not $ENV{"LIB"}) {
21679 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21680 }
21681}
21682
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021683sub diffSets($$)
21684{
21685 my ($S1, $S2) = @_;
21686 my @SK1 = keys(%{$S1});
21687 my @SK2 = keys(%{$S2});
21688 if($#SK1!=$#SK2) {
21689 return 1;
21690 }
21691 foreach my $K1 (@SK1)
21692 {
21693 if(not defined $S2->{$K1}) {
21694 return 1;
21695 }
21696 }
21697 return 0;
21698}
21699
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021700sub defaultDumpPath($$)
21701{
21702 my ($N, $V) = @_;
21703 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21704}
21705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021706sub create_ABI_Dump()
21707{
21708 if(not -e $DumpAPI) {
21709 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21710 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021711
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021712 my @DParts = split(/\s*,\s*/, $DumpAPI);
21713 foreach my $Part (@DParts)
21714 {
21715 if(not -e $Part) {
21716 exitStatus("Access_Error", "can't access \'$Part\'");
21717 }
21718 }
21719 checkVersionNum(1, $DumpAPI);
21720 foreach my $Part (@DParts)
21721 {
21722 if(isDump($Part)) {
21723 read_ABI_Dump(1, $Part);
21724 }
21725 else {
21726 readDescriptor(1, createDescriptor(1, $Part));
21727 }
21728 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021729
21730 if(not $Descriptor{1}{"Version"})
21731 { # set to default: X
21732 $Descriptor{1}{"Version"} = "X";
21733 }
21734
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021735 initLogging(1);
21736 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021737
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021738 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021739 if($OutputDumpPath)
21740 { # user defined path
21741 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021742 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021743 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21744
21745 if(not $Archive and not $StdOut)
21746 { # check archive utilities
21747 if($OSgroup eq "windows")
21748 { # using zip
21749 my $ZipCmd = get_CmdPath("zip");
21750 if(not $ZipCmd) {
21751 exitStatus("Not_Found", "can't find \"zip\"");
21752 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021753 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021754 else
21755 { # using tar and gzip
21756 my $TarCmd = get_CmdPath("tar");
21757 if(not $TarCmd) {
21758 exitStatus("Not_Found", "can't find \"tar\"");
21759 }
21760 my $GzipCmd = get_CmdPath("gzip");
21761 if(not $GzipCmd) {
21762 exitStatus("Not_Found", "can't find \"gzip\"");
21763 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021764 }
21765 }
21766
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021767 if(not $Descriptor{1}{"Dump"})
21768 {
21769 if(not $CheckHeadersOnly) {
21770 readLibs(1);
21771 }
21772 if($CheckHeadersOnly) {
21773 setLanguage(1, "C++");
21774 }
21775 if(not $CheckObjectsOnly) {
21776 searchForHeaders(1);
21777 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021778 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021779 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021780 if(not $Descriptor{1}{"Dump"})
21781 {
21782 if($Descriptor{1}{"Headers"}) {
21783 readHeaders(1);
21784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021785 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021786 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021787 if(not keys(%{$SymbolInfo{1}}))
21788 { # check if created dump is valid
21789 if(not $ExtendedCheck and not $CheckObjectsOnly)
21790 {
21791 if($CheckHeadersOnly) {
21792 exitStatus("Empty_Set", "the set of public symbols is empty");
21793 }
21794 else {
21795 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21796 }
21797 }
21798 }
21799 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021800 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021801 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21802 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021803 if($ExtraDump)
21804 { # add unmangled names to the ABI dump
21805 my @Names = ();
21806 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21807 {
21808 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21809 push(@Names, $MnglName);
21810 }
21811 }
21812 translateSymbols(@Names, 1);
21813 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21814 {
21815 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21816 {
21817 if(my $Unmangled = $tr_name{$MnglName})
21818 {
21819 if($MnglName ne $Unmangled) {
21820 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21821 }
21822 }
21823 }
21824 }
21825 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021826
21827 my %GccConstants = (); # built-in GCC constants
21828 foreach my $Name (keys(%{$Constants{1}}))
21829 {
21830 if(not defined $Constants{1}{$Name}{"Header"})
21831 {
21832 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21833 delete($Constants{1}{$Name});
21834 }
21835 }
21836
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021837 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021838 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021839 "TypeInfo" => $TypeInfo{1},
21840 "SymbolInfo" => $SymbolInfo{1},
21841 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021842 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021843 "SymbolVersion" => $SymVer{1},
21844 "LibraryVersion" => $Descriptor{1}{"Version"},
21845 "LibraryName" => $TargetLibraryName,
21846 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021847 "SkipTypes" => $SkipTypes{1},
21848 "SkipSymbols" => $SkipSymbols{1},
21849 "SkipNameSpaces" => $SkipNameSpaces{1},
21850 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021851 "Headers" => \%HeadersInfo,
21852 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021853 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021854 "NameSpaces" => $NestedNameSpaces{1},
21855 "Target" => $OStarget,
21856 "Arch" => getArch(1),
21857 "WordSize" => $WORD_SIZE{1},
21858 "GccVersion" => get_dumpversion($GCC_PATH),
21859 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21860 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21861 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021862 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021863 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021864 }
21865 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021866 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021868 if($ExtendedCheck)
21869 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021870 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021871 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021872 if($BinaryOnly)
21873 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021874 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021875 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021876 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021877 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021878 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021879 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21880 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021881 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021882
21883 my $ABI_DUMP = "";
21884 if($UseXML)
21885 {
21886 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021887 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021889 else
21890 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021891 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021893 if($StdOut)
21894 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021895 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021896 printMsg("INFO", "ABI dump has been generated to stdout");
21897 return;
21898 }
21899 else
21900 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021901 my ($DDir, $DName) = separate_path($DumpPath);
21902 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021903 if(not $Archive) {
21904 $DPath = $DumpPath;
21905 }
21906
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021907 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021908
21909 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021910 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021911 close(DUMP);
21912
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021913 if(not -s $DPath) {
21914 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21915 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021916 if($Archive) {
21917 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021918 }
21919
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021920 if($OutputDumpPath) {
21921 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021922 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021923 else {
21924 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21925 }
21926 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 +040021927 }
21928}
21929
21930sub quickEmptyReports()
21931{ # Quick "empty" reports
21932 # 4 times faster than merging equal dumps
21933 # NOTE: the dump contains the "LibraryVersion" attribute
21934 # if you change the version, then your dump will be different
21935 # OVERCOME: use -v1 and v2 options for comparing dumps
21936 # and don't change version in the XML descriptor (and dumps)
21937 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21938 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21939 {
21940 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21941 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21942 if($FilePath1 and $FilePath2)
21943 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021944 my $Line = readLineNum($FilePath1, 0);
21945 if($Line=~/xml/)
21946 { # XML format
21947 # is not supported yet
21948 return;
21949 }
21950
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021951 local $/ = undef;
21952
21953 open(DUMP1, $FilePath1);
21954 my $Content1 = <DUMP1>;
21955 close(DUMP1);
21956
21957 open(DUMP2, $FilePath2);
21958 my $Content2 = <DUMP2>;
21959 close(DUMP2);
21960
21961 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021962 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021963 # clean memory
21964 undef $Content2;
21965
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021966 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021967 my $ABIdump = eval($Content1);
21968
21969 # clean memory
21970 undef $Content1;
21971
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021972 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021973 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 +040021974 }
21975 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021976 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021977 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21978 }
21979 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021980 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021981 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21982 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021983 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021984 read_Libs_DumpInfo($ABIdump, 1);
21985 read_Machine_DumpInfo($ABIdump, 1);
21986 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021987
21988 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21989 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21990
21991 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21992 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21993
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021994 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21995 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21996 exitReport();
21997 }
21998 }
21999 }
22000}
22001
22002sub initLogging($)
22003{
22004 my $LibVersion = $_[0];
22005 # create log directory
22006 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22007 if($OutputLogPath{$LibVersion})
22008 { # user-defined by -log-path option
22009 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22010 }
22011 if($LogMode ne "n") {
22012 mkpath($LOG_DIR);
22013 }
22014 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022015 if($Debug)
22016 { # debug directory
22017 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022018
22019 if(not $ExtraInfo)
22020 { # enable --extra-info
22021 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022023 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022024 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022025}
22026
22027sub writeLog($$)
22028{
22029 my ($LibVersion, $Msg) = @_;
22030 if($LogMode ne "n") {
22031 appendFile($LOG_PATH{$LibVersion}, $Msg);
22032 }
22033}
22034
22035sub resetLogging($)
22036{
22037 my $LibVersion = $_[0];
22038 if($LogMode!~/a|n/)
22039 { # remove old log
22040 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022041 if($Debug) {
22042 rmtree($DEBUG_PATH{$LibVersion});
22043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022044 }
22045}
22046
22047sub printErrorLog($)
22048{
22049 my $LibVersion = $_[0];
22050 if($LogMode ne "n") {
22051 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22052 }
22053}
22054
22055sub isDump($)
22056{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022057 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22058 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022059 return $1;
22060 }
22061 return 0;
22062}
22063
22064sub isDump_U($)
22065{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022066 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022067 return $1;
22068 }
22069 return 0;
22070}
22071
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022072sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022073{
22074 # read input XML descriptors or ABI dumps
22075 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022076 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022077 }
22078 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
22079 foreach my $Part (@DParts1)
22080 {
22081 if(not -e $Part) {
22082 exitStatus("Access_Error", "can't access \'$Part\'");
22083 }
22084 }
22085 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022086 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022087 }
22088 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22089 foreach my $Part (@DParts2)
22090 {
22091 if(not -e $Part) {
22092 exitStatus("Access_Error", "can't access \'$Part\'");
22093 }
22094 }
22095 detect_default_paths("bin"); # to extract dumps
22096 if($#DParts1==0 and $#DParts2==0
22097 and isDump($Descriptor{1}{"Path"})
22098 and isDump($Descriptor{2}{"Path"}))
22099 { # optimization: equal ABI dumps
22100 quickEmptyReports();
22101 }
22102 checkVersionNum(1, $Descriptor{1}{"Path"});
22103 checkVersionNum(2, $Descriptor{2}{"Path"});
22104 printMsg("INFO", "preparation, please wait ...");
22105 foreach my $Part (@DParts1)
22106 {
22107 if(isDump($Part)) {
22108 read_ABI_Dump(1, $Part);
22109 }
22110 else {
22111 readDescriptor(1, createDescriptor(1, $Part));
22112 }
22113 }
22114 foreach my $Part (@DParts2)
22115 {
22116 if(isDump($Part)) {
22117 read_ABI_Dump(2, $Part);
22118 }
22119 else {
22120 readDescriptor(2, createDescriptor(2, $Part));
22121 }
22122 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022123
22124 if(not $Descriptor{1}{"Version"})
22125 { # set to default: X
22126 $Descriptor{1}{"Version"} = "X";
22127 }
22128
22129 if(not $Descriptor{2}{"Version"})
22130 { # set to default: Y
22131 $Descriptor{2}{"Version"} = "Y";
22132 }
22133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022134 initLogging(1);
22135 initLogging(2);
22136 # check consistency
22137 if(not $Descriptor{1}{"Headers"}
22138 and not $Descriptor{1}{"Libs"}) {
22139 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22140 }
22141 if(not $Descriptor{2}{"Headers"}
22142 and not $Descriptor{2}{"Libs"}) {
22143 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22144 }
22145 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22146 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22147 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22148 }
22149 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22150 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22151 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22152 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022153 if(not $Descriptor{1}{"Headers"})
22154 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022155 if($CheckHeadersOnly_Opt) {
22156 exitStatus("Error", "can't find header files info in descriptor d1");
22157 }
22158 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022159 if(not $Descriptor{2}{"Headers"})
22160 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022161 if($CheckHeadersOnly_Opt) {
22162 exitStatus("Error", "can't find header files info in descriptor d2");
22163 }
22164 }
22165 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022166 or not $Descriptor{2}{"Headers"})
22167 {
22168 if(not $CheckObjectsOnly_Opt)
22169 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022170 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22171 $CheckObjectsOnly = 1;
22172 }
22173 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022174 if(not $Descriptor{1}{"Libs"})
22175 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022176 if($CheckObjectsOnly_Opt) {
22177 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22178 }
22179 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022180 if(not $Descriptor{2}{"Libs"})
22181 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022182 if($CheckObjectsOnly_Opt) {
22183 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22184 }
22185 }
22186 if(not $Descriptor{1}{"Libs"}
22187 or not $Descriptor{2}{"Libs"})
22188 { # comparing standalone header files
22189 # comparing ABI dumps created with --headers-only
22190 if(not $CheckHeadersOnly_Opt)
22191 {
22192 printMsg("WARNING", "checking headers only");
22193 $CheckHeadersOnly = 1;
22194 }
22195 }
22196 if($UseDumps)
22197 { # --use-dumps
22198 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022199 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22200 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022201
22202 unlink($DumpPath1);
22203 unlink($DumpPath2);
22204
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022205 my $pid = fork();
22206 if($pid)
22207 { # dump on two CPU cores
22208 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22209 if($RelativeDirectory{1}) {
22210 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22211 }
22212 if($OutputLogPath{1}) {
22213 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22214 }
22215 if($CrossGcc) {
22216 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22217 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022218 if($Quiet)
22219 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022220 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022221 @PARAMS = (@PARAMS, "-logging-mode", "a");
22222 }
22223 elsif($LogMode and $LogMode ne "w")
22224 { # "w" is default
22225 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022226 }
22227 if($ExtendedCheck) {
22228 @PARAMS = (@PARAMS, "-extended");
22229 }
22230 if($UserLang) {
22231 @PARAMS = (@PARAMS, "-lang", $UserLang);
22232 }
22233 if($TargetVersion{1}) {
22234 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022236 if($BinaryOnly) {
22237 @PARAMS = (@PARAMS, "-binary");
22238 }
22239 if($SourceOnly) {
22240 @PARAMS = (@PARAMS, "-source");
22241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022242 if($SortDump) {
22243 @PARAMS = (@PARAMS, "-sort");
22244 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022245 if($DumpFormat and $DumpFormat ne "perl") {
22246 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22247 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022248 if($CheckHeadersOnly) {
22249 @PARAMS = (@PARAMS, "-headers-only");
22250 }
22251 if($CheckObjectsOnly) {
22252 @PARAMS = (@PARAMS, "-objects-only");
22253 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022254 if($Debug)
22255 {
22256 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022257 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022259 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022260 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022261 exit(1);
22262 }
22263 }
22264 else
22265 { # child
22266 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22267 if($RelativeDirectory{2}) {
22268 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22269 }
22270 if($OutputLogPath{2}) {
22271 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22272 }
22273 if($CrossGcc) {
22274 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22275 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022276 if($Quiet)
22277 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022278 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022279 @PARAMS = (@PARAMS, "-logging-mode", "a");
22280 }
22281 elsif($LogMode and $LogMode ne "w")
22282 { # "w" is default
22283 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022284 }
22285 if($ExtendedCheck) {
22286 @PARAMS = (@PARAMS, "-extended");
22287 }
22288 if($UserLang) {
22289 @PARAMS = (@PARAMS, "-lang", $UserLang);
22290 }
22291 if($TargetVersion{2}) {
22292 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22293 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022294 if($BinaryOnly) {
22295 @PARAMS = (@PARAMS, "-binary");
22296 }
22297 if($SourceOnly) {
22298 @PARAMS = (@PARAMS, "-source");
22299 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022300 if($SortDump) {
22301 @PARAMS = (@PARAMS, "-sort");
22302 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022303 if($DumpFormat and $DumpFormat ne "perl") {
22304 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22305 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022306 if($CheckHeadersOnly) {
22307 @PARAMS = (@PARAMS, "-headers-only");
22308 }
22309 if($CheckObjectsOnly) {
22310 @PARAMS = (@PARAMS, "-objects-only");
22311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022312 if($Debug)
22313 {
22314 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022315 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022317 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022318 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022319 exit(1);
22320 }
22321 else {
22322 exit(0);
22323 }
22324 }
22325 waitpid($pid, 0);
22326 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022327 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22328 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022329 if($TargetLibraryFName ne $TargetLibraryName) {
22330 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22331 }
22332 if($ShowRetVal) {
22333 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22334 }
22335 if($CrossGcc) {
22336 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22337 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022338 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22339 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022340 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022341 }
22342 if($ReportFormat and $ReportFormat ne "html")
22343 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022344 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22345 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022346 if($OutputReportPath) {
22347 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22348 }
22349 if($BinaryReportPath) {
22350 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22351 }
22352 if($SourceReportPath) {
22353 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22354 }
22355 if($LoggingPath) {
22356 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22357 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022358 if($CheckHeadersOnly) {
22359 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22360 }
22361 if($CheckObjectsOnly) {
22362 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22363 }
22364 if($BinaryOnly) {
22365 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22366 }
22367 if($SourceOnly) {
22368 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22369 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022370 if($Debug)
22371 {
22372 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22373 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022375 system("perl", $0, @CMP_PARAMS);
22376 exit($?>>8);
22377 }
22378 if(not $Descriptor{1}{"Dump"}
22379 or not $Descriptor{2}{"Dump"})
22380 { # need GCC toolchain to analyze
22381 # header files and libraries
22382 detect_default_paths("inc|lib|gcc");
22383 }
22384 if(not $Descriptor{1}{"Dump"})
22385 {
22386 if(not $CheckHeadersOnly) {
22387 readLibs(1);
22388 }
22389 if($CheckHeadersOnly) {
22390 setLanguage(1, "C++");
22391 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022392 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022393 searchForHeaders(1);
22394 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022395 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022396 }
22397 if(not $Descriptor{2}{"Dump"})
22398 {
22399 if(not $CheckHeadersOnly) {
22400 readLibs(2);
22401 }
22402 if($CheckHeadersOnly) {
22403 setLanguage(2, "C++");
22404 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022405 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022406 searchForHeaders(2);
22407 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022408 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022409 }
22410 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22411 { # support for old ABI dumps
22412 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022413 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022414 {
22415 $WORD_SIZE{1} = $WORD_SIZE{2};
22416 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22417 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022418 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022419 {
22420 $WORD_SIZE{2} = $WORD_SIZE{1};
22421 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22422 }
22423 }
22424 elsif(not $WORD_SIZE{1}
22425 and not $WORD_SIZE{2})
22426 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022427 $WORD_SIZE{1} = "4";
22428 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022429 }
22430 if($Descriptor{1}{"Dump"})
22431 { # support for old ABI dumps
22432 prepareTypes(1);
22433 }
22434 if($Descriptor{2}{"Dump"})
22435 { # support for old ABI dumps
22436 prepareTypes(2);
22437 }
22438 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22439 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22440 }
22441 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442 if(not $CheckObjectsOnly)
22443 {
22444 if($Descriptor{1}{"Headers"}
22445 and not $Descriptor{1}{"Dump"}) {
22446 readHeaders(1);
22447 }
22448 if($Descriptor{2}{"Headers"}
22449 and not $Descriptor{2}{"Dump"}) {
22450 readHeaders(2);
22451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022452 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022453
22454 # clean memory
22455 %SystemHeaders = ();
22456 %mangled_name_gcc = ();
22457
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022458 prepareSymbols(1);
22459 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022460
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022461 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022462 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022463
22464 # Virtual Tables
22465 registerVTable(1);
22466 registerVTable(2);
22467
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022468 if(not checkDump(1, "1.22")
22469 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022470 { # support for old ABI dumps
22471 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22472 {
22473 if($ClassName=~/</)
22474 { # templates
22475 if(not defined $VirtualTable{1}{$ClassName})
22476 { # synchronize
22477 delete($VirtualTable{2}{$ClassName});
22478 }
22479 }
22480 }
22481 }
22482
22483 registerOverriding(1);
22484 registerOverriding(2);
22485
22486 setVirtFuncPositions(1);
22487 setVirtFuncPositions(2);
22488
22489 # Other
22490 addParamNames(1);
22491 addParamNames(2);
22492
22493 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022494}
22495
22496sub compareAPIs($)
22497{
22498 my $Level = $_[0];
22499 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022500 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022501 if($Level eq "Binary") {
22502 printMsg("INFO", "comparing ABIs ...");
22503 }
22504 else {
22505 printMsg("INFO", "comparing APIs ...");
22506 }
22507 if($CheckHeadersOnly
22508 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022509 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022510 detectAdded_H($Level);
22511 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022512 }
22513 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022514 { # added/removed in libs
22515 detectAdded($Level);
22516 detectRemoved($Level);
22517 }
22518 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022519 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022520 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022521 if(keys(%{$CheckedSymbols{$Level}})) {
22522 mergeConstants($Level);
22523 }
22524 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022525
22526 $Cache{"mergeTypes"} = (); # free memory
22527
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022528 if($CheckHeadersOnly
22529 or $Level eq "Source")
22530 { # added/removed in headers
22531 mergeHeaders($Level);
22532 }
22533 else
22534 { # added/removed in libs
22535 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022536 }
22537}
22538
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022539sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022540{
22541 my %Opts = (
22542 "OStarget"=>$OStarget,
22543 "Debug"=>$Debug,
22544 "Quiet"=>$Quiet,
22545 "LogMode"=>$LogMode,
22546 "CheckHeadersOnly"=>$CheckHeadersOnly,
22547
22548 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022549 "GCC_PATH"=>$GCC_PATH,
22550 "TargetSysInfo"=>$TargetSysInfo,
22551 "CrossPrefix"=>$CrossPrefix,
22552 "TargetLibraryName"=>$TargetLibraryName,
22553 "CrossGcc"=>$CrossGcc,
22554 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022555 "NoStdInc"=>$NoStdInc,
22556
22557 "BinaryOnly" => $BinaryOnly,
22558 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 );
22560 return \%Opts;
22561}
22562
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022563sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022564{
22565 my %CODE_ERROR = reverse(%ERROR_CODE);
22566 return $CODE_ERROR{$_[0]};
22567}
22568
22569sub scenario()
22570{
22571 if($StdOut)
22572 { # enable quiet mode
22573 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022574 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022575 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022576 if(not $LogMode)
22577 { # default
22578 $LogMode = "w";
22579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022580 if($UserLang)
22581 { # --lang=C++
22582 $UserLang = uc($UserLang);
22583 $COMMON_LANGUAGE{1}=$UserLang;
22584 $COMMON_LANGUAGE{2}=$UserLang;
22585 }
22586 if($LoggingPath)
22587 {
22588 $OutputLogPath{1} = $LoggingPath;
22589 $OutputLogPath{2} = $LoggingPath;
22590 if($Quiet) {
22591 $COMMON_LOG_PATH = $LoggingPath;
22592 }
22593 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022594 if($Quick) {
22595 $ADD_TMPL_INSTANCES = 0;
22596 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022597 if($OutputDumpPath)
22598 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022599 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022600 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22601 }
22602 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022603 if($BinaryOnly and $SourceOnly)
22604 { # both --binary and --source
22605 # is the default mode
22606 $DoubleReport = 1;
22607 $JoinReport = 0;
22608 $BinaryOnly = 0;
22609 $SourceOnly = 0;
22610 if($OutputReportPath)
22611 { # --report-path
22612 $DoubleReport = 0;
22613 $JoinReport = 1;
22614 }
22615 }
22616 elsif($BinaryOnly or $SourceOnly)
22617 { # --binary or --source
22618 $DoubleReport = 0;
22619 $JoinReport = 0;
22620 }
22621 if($UseXML)
22622 { # --xml option
22623 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022624 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022626 if($ReportFormat)
22627 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022628 $ReportFormat = lc($ReportFormat);
22629 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022630 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022631 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022632 if($ReportFormat eq "htm")
22633 { # HTM == HTML
22634 $ReportFormat = "html";
22635 }
22636 elsif($ReportFormat eq "xml")
22637 { # --report-format=XML equal to --xml
22638 $UseXML = 1;
22639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022640 }
22641 else
22642 { # default: HTML
22643 $ReportFormat = "html";
22644 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022645 if($DumpFormat)
22646 { # validate
22647 $DumpFormat = lc($DumpFormat);
22648 if($DumpFormat!~/\A(xml|perl)\Z/) {
22649 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22650 }
22651 if($DumpFormat eq "xml")
22652 { # --dump-format=XML equal to --xml
22653 $UseXML = 1;
22654 }
22655 }
22656 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022657 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022658 $DumpFormat = "perl";
22659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022660 if($Quiet and $LogMode!~/a|n/)
22661 { # --quiet log
22662 if(-f $COMMON_LOG_PATH) {
22663 unlink($COMMON_LOG_PATH);
22664 }
22665 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022666 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022667 $CheckUndefined = 1;
22668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022669 if($TestTool and $UseDumps)
22670 { # --test && --use-dumps == --test-dump
22671 $TestDump = 1;
22672 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022673 if($Tolerant)
22674 { # enable all
22675 $Tolerance = 1234;
22676 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022677 if($Help)
22678 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022679 HELP_MESSAGE();
22680 exit(0);
22681 }
22682 if($InfoMsg) {
22683 INFO_MESSAGE();
22684 exit(0);
22685 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022686 if($ShowVersion)
22687 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022688 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 +040022689 exit(0);
22690 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022691 if($DumpVersion)
22692 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022693 printMsg("INFO", $TOOL_VERSION);
22694 exit(0);
22695 }
22696 if($ExtendedCheck) {
22697 $CheckHeadersOnly = 1;
22698 }
22699 if($SystemRoot_Opt)
22700 { # user defined root
22701 if(not -e $SystemRoot_Opt) {
22702 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22703 }
22704 $SystemRoot = $SystemRoot_Opt;
22705 $SystemRoot=~s/[\/]+\Z//g;
22706 if($SystemRoot) {
22707 $SystemRoot = get_abs_path($SystemRoot);
22708 }
22709 }
22710 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022711
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022712 if($SortDump)
22713 {
22714 $Data::Dumper::Useperl = 1;
22715 $Data::Dumper::Sortkeys = \&dump_sorting;
22716 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022717
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022718 if($TargetLibsPath)
22719 {
22720 if(not -f $TargetLibsPath) {
22721 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22722 }
22723 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22724 $TargetLibs{$Lib} = 1;
22725 }
22726 }
22727 if($TargetHeadersPath)
22728 { # --headers-list
22729 if(not -f $TargetHeadersPath) {
22730 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22731 }
22732 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22733 {
22734 $TargetHeaders{1}{$Header} = 1;
22735 $TargetHeaders{2}{$Header} = 1;
22736 }
22737 }
22738 if($TargetHeader)
22739 { # --header
22740 $TargetHeaders{1}{$TargetHeader} = 1;
22741 $TargetHeaders{2}{$TargetHeader} = 1;
22742 }
22743 if($TestTool
22744 or $TestDump)
22745 { # --test, --test-dump
22746 detect_default_paths("bin|gcc"); # to compile libs
22747 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022748 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022749 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022750 exit(0);
22751 }
22752 if($DumpSystem)
22753 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022754
22755 if(not $TargetSysInfo) {
22756 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22757 }
22758
22759 if(not -d $TargetSysInfo) {
22760 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22761 }
22762
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022763 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022764 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022765 { # system XML descriptor
22766 if(not -f $DumpSystem) {
22767 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22768 }
22769 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022770 foreach (@{$Ret->{"Tools"}})
22771 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022772 push_U($SystemPaths{"bin"}, $_);
22773 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022774 }
22775 if($Ret->{"CrossPrefix"}) {
22776 $CrossPrefix = $Ret->{"CrossPrefix"};
22777 }
22778 }
22779 elsif($SystemRoot_Opt)
22780 { # -sysroot "/" option
22781 # default target: /usr/lib, /usr/include
22782 # search libs: /usr/lib and /lib
22783 if(not -e $SystemRoot."/usr/lib") {
22784 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22785 }
22786 if(not -e $SystemRoot."/lib") {
22787 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22788 }
22789 if(not -e $SystemRoot."/usr/include") {
22790 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22791 }
22792 readSystemDescriptor("
22793 <name>
22794 $DumpSystem
22795 </name>
22796 <headers>
22797 $SystemRoot/usr/include
22798 </headers>
22799 <libs>
22800 $SystemRoot/usr/lib
22801 </libs>
22802 <search_libs>
22803 $SystemRoot/lib
22804 </search_libs>");
22805 }
22806 else {
22807 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22808 }
22809 detect_default_paths("bin|gcc"); # to check symbols
22810 if($OStarget eq "windows")
22811 { # to run dumpbin.exe
22812 # and undname.exe
22813 check_win32_env();
22814 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022815 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022816 exit(0);
22817 }
22818 if($CmpSystems)
22819 { # --cmp-systems
22820 detect_default_paths("bin"); # to extract dumps
22821 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022822 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022823 exit(0);
22824 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022825 if($GenerateTemplate)
22826 {
22827 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22828 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022829 exit(0);
22830 }
22831 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022832 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022833 }
22834 else
22835 { # validate library name
22836 if($TargetLibraryName=~/[\*\/\\]/) {
22837 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22838 }
22839 }
22840 if(not $TargetLibraryFName) {
22841 $TargetLibraryFName = $TargetLibraryName;
22842 }
22843 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22844 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22845 }
22846 if($SymbolsListPath)
22847 {
22848 if(not -f $SymbolsListPath) {
22849 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22850 }
22851 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22852 $SymbolsList{$Interface} = 1;
22853 }
22854 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022855 if($TypesListPath)
22856 {
22857 if(not -f $TypesListPath) {
22858 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22859 }
22860 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22861 $TypesList{$Type} = 1;
22862 }
22863 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022864 if($SkipSymbolsListPath)
22865 {
22866 if(not -f $SkipSymbolsListPath) {
22867 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22868 }
22869 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22870 $SkipSymbolsList{$Interface} = 1;
22871 }
22872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022873 if($SkipHeadersPath)
22874 {
22875 if(not -f $SkipHeadersPath) {
22876 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22877 }
22878 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022879 { # register for both versions
22880 $SkipHeadersList{1}{$Path} = 1;
22881 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022882 my ($CPath, $Type) = classifyPath($Path);
22883 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022884 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022885 }
22886 }
22887 if($ParamNamesPath)
22888 {
22889 if(not -f $ParamNamesPath) {
22890 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22891 }
22892 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22893 {
22894 if($Line=~s/\A(\w+)\;//)
22895 {
22896 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022897 if($Line=~/;(\d+);/)
22898 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022899 while($Line=~s/(\d+);(\w+)//) {
22900 $AddIntParams{$Interface}{$1}=$2;
22901 }
22902 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022903 else
22904 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022905 my $Num = 0;
22906 foreach my $Name (split(/;/, $Line)) {
22907 $AddIntParams{$Interface}{$Num++}=$Name;
22908 }
22909 }
22910 }
22911 }
22912 }
22913 if($AppPath)
22914 {
22915 if(not -f $AppPath) {
22916 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22917 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022918 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022919 $SymbolsList_App{$Interface} = 1;
22920 }
22921 }
22922 if($DumpAPI)
22923 { # --dump-abi
22924 # make an API dump
22925 create_ABI_Dump();
22926 exit($COMPILE_ERRORS);
22927 }
22928 # default: compare APIs
22929 # -d1 <path>
22930 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022931 compareInit();
22932 if($JoinReport or $DoubleReport)
22933 {
22934 compareAPIs("Binary");
22935 compareAPIs("Source");
22936 }
22937 elsif($BinaryOnly) {
22938 compareAPIs("Binary");
22939 }
22940 elsif($SourceOnly) {
22941 compareAPIs("Source");
22942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022943 exitReport();
22944}
22945
22946scenario();